<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"yoursite.com","root":"/","scheme":"Gemini","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"always","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="基本语法语句&#x3D;&#x3D;JavaScript 程序的执行单位为行，也就是一行一行地执行。&#x3D;&#x3D; 一般情况下，每一行就是一个语句。 语句是为了完成某种任务而进行的操作，比如下面就是一行赋值语句。 1var a &#x3D; 1 + 3;  1 + 3 叫做表达式，指一个为了得到返回值的计算式。 &#x3D;&#x3D;语句和表达式的区别在于，前者主要为了进行某种操作，一般情况下不需要返回值；后者则是为了得到返回值，一定会返回一个值。&#x3D;&#x3D;">
<meta property="og:type" content="website">
<meta property="og:title" content="JavaScript">
<meta property="og:url" content="http://yoursite.com/JavaScript/index.html">
<meta property="og:site_name" content="Albert Guo">
<meta property="og:description" content="基本语法语句&#x3D;&#x3D;JavaScript 程序的执行单位为行，也就是一行一行地执行。&#x3D;&#x3D; 一般情况下，每一行就是一个语句。 语句是为了完成某种任务而进行的操作，比如下面就是一行赋值语句。 1var a &#x3D; 1 + 3;  1 + 3 叫做表达式，指一个为了得到返回值的计算式。 &#x3D;&#x3D;语句和表达式的区别在于，前者主要为了进行某种操作，一般情况下不需要返回值；后者则是为了得到返回值，一定会返回一个值。&#x3D;&#x3D;">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://inews.gtimg.com/newsapp_ls/0/12133946205/0">
<meta property="og:image" content="https://inews.gtimg.com/newsapp_ls/0/12133956641/0">
<meta property="article:published_time" content="2020-06-29T09:50:28.000Z">
<meta property="article:modified_time" content="2020-08-03T11:07:43.837Z">
<meta property="article:author" content="Albert Guo">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://inews.gtimg.com/newsapp_ls/0/12133946205/0">

<link rel="canonical" href="http://yoursite.com/JavaScript/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : false,
    lang   : 'zh-CN'
  };
</script>

  <title>JavaScript | Albert Guo
</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Albert Guo</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-bars fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-address-card fa-fw"></i>简介</a>

  </li>
        <li class="menu-item menu-item-webpack">

    <a href="/webpack/" rel="section"><i class="fa fa-bookmark fa-fw"></i>webpack</a>

  </li>
        <li class="menu-item menu-item-javascript">

    <a href="/JavaScript/" rel="section"><i class="fa fa-bookmark fa-fw"></i>ECMAScript 5.1</a>

  </li>
        <li class="menu-item menu-item-ecmascript6">

    <a href="/ECMAScript6/" rel="section"><i class="fa fa-bookmark fa-fw"></i>ECMAScript 6</a>

  </li>
        <li class="menu-item menu-item-react">

    <a href="/React/" rel="section"><i class="fa fa-bookmark fa-fw"></i>React</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          
  
  

          <div class="content page posts-expand">
            

    
    
    
    <div class="post-block" lang="zh-CN">
      <header class="post-header">

<h1 class="post-title" itemprop="name headline">JavaScript
</h1>

<div class="post-meta">
  

</div>

</header>

      
      
      
      <div class="post-body">
          <h1 id="基本语法"><a href="#基本语法" class="headerlink" title="基本语法"></a>基本语法</h1><h2 id="语句"><a href="#语句" class="headerlink" title="语句"></a>语句</h2><p>==JavaScript 程序的执行单位为行，也就是一行一行地执行。== 一般情况下，每一行就是一个语句。</p>
<p>语句是为了完成某种任务而进行的操作，比如下面就是一行赋值语句。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">1</span> + <span class="number">3</span>;</span><br></pre></td></tr></table></figure>

<p><code>1 + 3</code> 叫做表达式，指一个为了得到返回值的计算式。</p>
<p>==语句和表达式的区别在于，前者主要为了进行某种操作，一般情况下不需要返回值；后者则是为了得到返回值，一定会返回一个值。==</p>
<h2 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h2><h3 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h3><p>变量是对“值”的具名引用。变量就是为“值”起名，然后引用这个名字，就等同于引用这个值。变量的名字就是变量名。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">1</span>;</span><br></pre></td></tr></table></figure>

<p>注意，==JavaScript 的变量名区分大小写，A 和 a 是两个不同的变量。==</p>
<h3 id="变量提升"><a href="#变量提升" class="headerlink" title="变量提升"></a>变量提升</h3><p>==JavaScript 引擎的工作方式是，先解析代码，获取所有被声明的变量，然后再一行一行地运行。这造成的结果，就是所有的变量的声明语句，都会被提升到代码的头部，这就叫做变量提升。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(a); </span><br><span class="line"><span class="keyword">var</span> a = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 提升后</span></span><br><span class="line"><span class="keyword">var</span> a;</span><br><span class="line"><span class="built_in">console</span>.log(a); <span class="comment">// undefined</span></span><br><span class="line">a = <span class="number">1</span>;</span><br></pre></td></tr></table></figure>

<h2 id="标识符"><a href="#标识符" class="headerlink" title="标识符"></a>标识符</h2><p>标识符指的是用来识别各种值的合法名称。最常见的标识符就是变量名，以及后面要提到的函数名。==JavaScript 语言的标识符对大小写敏感，所以 a 和 A 是两个不同的标识符。==</p>
<p>标识符命名规则：</p>
<ul>
<li>第一个字符，可以是任意 <code>Unicode</code>。</li>
<li>字母（包括英文字母和其他语言的字母），以及美元符号 $ 和下划线 _ 。</li>
<li>第二个字符及后面的字符，除了 <code>Unicode</code> 字母、美元符号和下划线，还可以用数字 <code>0-9</code>。</li>
</ul>
<p>JavaScript 有一些保留字，不能用作标识符：<code>arguments、break、case、catch、class、const、continue、debugger、default、delete、do、else、enum、eval、export、extends、false、finally、for、function、if、implements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、while、with、yield</code>。</p>
<h2 id="注释"><a href="#注释" class="headerlink" title="注释"></a>注释</h2><p>源码中被 JavaScript 引擎忽略的部分就叫做注释，它的作用是对代码进行解释。JavaScript 提供两种注释的写法：</p>
<ul>
<li>一种是单行注释，用 <code>//</code> 起头；</li>
<li>另一种是多行注释，放在 <code>/*</code> 和 <code>*/</code> 之间。</li>
</ul>
<h2 id="区块"><a href="#区块" class="headerlink" title="区块"></a>区块</h2><p>JavaScript 使用大括号，将多个相关的语句组合在一起，称为“区块”。</p>
<p>==对于 var 命令来说，JavaScript 的区块不构成单独的作用域。==</p>
<h2 id="条件语句"><a href="#条件语句" class="headerlink" title="条件语句"></a>条件语句</h2><h3 id="if-结构"><a href="#if-结构" class="headerlink" title="if 结构"></a>if 结构</h3><p><code>if</code> 结构先判断一个表达式的布尔值，然后根据布尔值的真伪，执行不同的语句。所谓布尔值，指的是 JavaScript 的两个特殊值，<code>true</code> 表示真，<code>false</code> 表示伪。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (布尔值)&#123;</span><br><span class="line">  语句;  </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h3 id="if-…-else-结构"><a href="#if-…-else-结构" class="headerlink" title="if … else 结构"></a>if … else 结构</h3><p><code>if</code> 代码块后面，还可以跟一个 <code>else</code> 代码块，表示不满足条件时，所要执行的代码。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (m === <span class="number">3</span>) &#123;</span><br><span class="line">  <span class="comment">// 满足条件时，执行的语句</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">  <span class="comment">// 不满足条件时，执行的语句</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (m === <span class="number">0</span>) &#123;</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (m === <span class="number">1</span>) &#123;</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (m === <span class="number">2</span>) &#123;</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="switch-结构"><a href="#switch-结构" class="headerlink" title="switch 结构"></a>switch 结构</h3><p>多个 <code>if ... else</code> 连在一起使用的时候，可以转为使用更方便的 <code>switch</code> 结构。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">switch</span> (fruit) &#123;</span><br><span class="line">  <span class="keyword">case</span> <span class="string">"banana"</span>:</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">  <span class="keyword">case</span> <span class="string">"apple"</span>:</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">    <span class="keyword">break</span>;</span><br><span class="line">  <span class="keyword">default</span>:</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上面代码根据变量 <code>fruit</code> 的值，选择执行相应的 <code>case</code>。如果所有 <code>case</code> 都不符合，则执行最后的 <code>default</code> 部分。==需要注意的是，每个 <code>case</code> 代码块内部的 <code>break</code> 语句不能少，否则会接下去执行下一个 <code>case</code> 代码块，而不是跳出 <code>switch</code> 结构。==</p>
<h3 id="三元运算符"><a href="#三元运算符" class="headerlink" title="三元运算符 ? :"></a>三元运算符 <code>? :</code></h3><p>JavaScript 还有一个三元运算符（即该运算符需要三个运算子）<code>x ? x : x</code>，也可以用于逻辑判断。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(条件) ? 表达式 1 : 表达式 2</span><br></pre></td></tr></table></figure>

<p>==上面代码中，如果“条件”为 <code>true</code>，则返回“表达式1”的值，否则返回“表达式2”的值。==</p>
<h2 id="循环语句"><a href="#循环语句" class="headerlink" title="循环语句"></a>循环语句</h2><p>循环语句用于重复执行某个操作，它有多种形式。</p>
<h3 id="while-循环"><a href="#while-循环" class="headerlink" title="while 循环"></a>while 循环</h3><p><code>while</code> 语句包括一个循环条件和一段代码块，只要条件为真，就不断循环执行代码块。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (条件) &#123;</span><br><span class="line">  语句;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="for-循环"><a href="#for-循环" class="headerlink" title="for 循环"></a>for 循环</h3><p><code>for</code> 语句是循环命令的另一种形式，可以指定循环的起点、终点和终止条件。它的格式如下。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">for (初始化表达式; 条件; 递增表达式) &#123;</span><br><span class="line">  语句</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><code>for</code> 语句后面的括号里面，有三个表达式：</p>
<ul>
<li>初始化表达式：确定循环变量的初始值，只在循环开始时执行一次。</li>
<li>条件表达式：每轮循环开始时，都要执行这个条件表达式，只有值为真，才继续进行循环。</li>
<li>递增表达式：每轮循环的最后一个操作，通常用来递增循环变量。</li>
</ul>
<h3 id="do-…-while-循环"><a href="#do-…-while-循环" class="headerlink" title="do … while 循环"></a>do … while 循环</h3><p><code>do ... while</code> 循环与 <code>while</code> 循环类似，唯一的区别就是先运行一次循环体，然后判断循环条件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">do &#123;</span><br><span class="line">  语句</span><br><span class="line">&#125; while (条件);</span><br></pre></td></tr></table></figure>

<p>不管条件是否为真，<code>do ... while</code> 循环至少运行一次，这是这种结构最大的特点。另外，==<code>while</code> 语句后面的分号注意不要省略。==</p>
<h3 id="break-语句和-continue-语句"><a href="#break-语句和-continue-语句" class="headerlink" title="break 语句和 continue 语句"></a>break 语句和 continue 语句</h3><p><code>break</code> 语句和 <code>continue</code> 语句都具有跳转作用，可以让代码不按既有的顺序执行。适用于 <code>while 、for</code> 循环等语句。</p>
<p>==<code>break</code>语句用于跳出代码块或循环。==</p>
<p>==<code>continue</code> 语句用于立即终止本轮循环，返回循环结构的头部，开始下一轮循环。==</p>
<hr>
<h1 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h1><h2 id="数据分类"><a href="#数据分类" class="headerlink" title="数据分类"></a>数据分类</h2><p>JavaScript 语言的每一个值，都属于某一种数据类型。JavaScript 的数据类型，共有 <code>7</code> 种。</p>
<ul>
<li>数值（<code>number</code>）：整数和小数（比如 <code>1</code> 和 <code>3.14</code>）</li>
<li>字符串（<code>string</code>）：文本（比如 <code>&#39;Hello World&#39;</code>）</li>
<li>布尔值（<code>boolean</code>）：表示真伪的两个特殊值，即 <code>true</code>（真）和 <code>false</code>（假）</li>
<li><code>undefined</code>：表示“未定义”或不存在，即由于目前没有定义，所以此处暂时没有任何值</li>
<li><code>null</code>：表示空值，即此处的值为空</li>
<li><code>Symbol</code>：表示独一无二的值（ES6 新增）</li>
<li>对象（<code>object</code>）：各种值组成的集合</li>
</ul>
<p>对象是最复杂的数据类型，又可以分成三个子类型。</p>
<ul>
<li>狭义的对象（<code>object</code>）</li>
<li>数组（<code>array</code>）</li>
<li>函数（<code>function</code>）</li>
<li>Set（ES6 新增）</li>
<li>Map（ES6 新增）</li>
</ul>
<h2 id="判断数据类型"><a href="#判断数据类型" class="headerlink" title="判断数据类型"></a>判断数据类型</h2><p>JavaScript 有三种方法，可以确定一个值到底是什么类型。</p>
<ul>
<li><code>typeof</code> 运算符（只能精准判断基本数据类型，复杂数据类型判断比较笼统）</li>
<li><code>instanceof</code> 运算符（判断复杂数据类型，而且比较笼统，不精准）</li>
<li><code>Object.prototype.toString</code> 方法（推荐使用）</li>
</ul>
<p>声明几个不同类型的变量，用于接下来案例使用。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="string">'a'</span>;</span><br><span class="line"><span class="keyword">var</span> aa = <span class="keyword">new</span> <span class="built_in">String</span>(<span class="string">'aaa'</span>);</span><br><span class="line"><span class="keyword">var</span> b = <span class="number">123</span>;</span><br><span class="line"><span class="keyword">var</span> c = <span class="literal">true</span>;</span><br><span class="line"><span class="keyword">var</span> d = <span class="literal">undefined</span>;</span><br><span class="line"><span class="keyword">var</span> e = <span class="literal">null</span>;</span><br><span class="line"><span class="keyword">var</span> f = &#123;&#125;;</span><br><span class="line"><span class="keyword">var</span> g = [<span class="string">'2'</span>];</span><br><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> <span class="built_in">Set</span>();   <span class="comment">// ES6 新增</span></span><br><span class="line"><span class="keyword">var</span> m = <span class="keyword">new</span> <span class="built_in">Map</span>();   <span class="comment">// ES6 新增</span></span><br><span class="line"><span class="keyword">var</span> sym = <span class="built_in">Symbol</span>(<span class="string">'123'</span>);   <span class="comment">// ES6 新增</span></span><br></pre></td></tr></table></figure>

<p><code>typeof</code> 运算符可以返回一个值的数据类型，只能精准判断基本数据类型，复杂数据类型判断比较笼统。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> a);   <span class="comment">// string</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> g);   <span class="comment">// Object</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> s);   <span class="comment">// Object</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> m);   <span class="comment">// Object</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> sym);   <span class="comment">// symbol</span></span><br></pre></td></tr></table></figure>

<p>数值、字符串、布尔值分别返回 <code>number、string、boolean</code>；函数返回 <code>function</code>、<code>undefined</code> 返回 <code>undefined</code>、对象返回 <code>object</code>、<code>null</code> 返回 <code>object</code>（历史原因）。</p>
<p><code>instanceof</code> 运算符，==只能判断复杂数据类型==，而且比较笼统，不精准。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(a <span class="keyword">instanceof</span> <span class="built_in">String</span>);   <span class="comment">// false</span></span><br><span class="line"><span class="built_in">console</span>.log(b <span class="keyword">instanceof</span> <span class="built_in">Number</span>);   <span class="comment">// false</span></span><br><span class="line"><span class="built_in">console</span>.log(aa <span class="keyword">instanceof</span> <span class="built_in">String</span>);   <span class="comment">// true （注意观察和字符串 a 的声明方式）</span></span><br><span class="line"><span class="built_in">console</span>.log(g <span class="keyword">instanceof</span> <span class="built_in">Object</span>);   <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p><code>Object.prototype.toString</code> 方法，配合 <code>call</code> 方法使用来判断数据类型，推荐使用。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Object</span>.prototype.toString.call(a));   <span class="comment">// [object String]</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Object</span>.prototype.toString.call(b));   <span class="comment">// [object Number]</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Object</span>.prototype.toString.call(g));   <span class="comment">// [object Array]</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Object</span>.prototype.toString.call(s));   <span class="comment">// [object Set]</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Object</span>.prototype.toString.call(m));   <span class="comment">// [object Map]</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Object</span>.prototype.toString.call(sym));   <span class="comment">// [object Symbol]</span></span><br></pre></td></tr></table></figure>

<h2 id="null-undefined-和布尔值"><a href="#null-undefined-和布尔值" class="headerlink" title="null, undefined 和布尔值"></a>null, undefined 和布尔值</h2><h3 id="null-和-undefined"><a href="#null-和-undefined" class="headerlink" title="null 和 undefined"></a>null 和 undefined</h3><p><code>null</code> 与 <code>undefined</code> 都可以表示“没有”，含义非常相似。将一个变量赋值为 <code>undefined</code> 或 <code>null</code>，语法效果几乎没区别。</p>
<p><code>null</code> 表示空值，即该处的值现在为空。调用函数时，某个参数未设置任何值，这时就可以传入 <code>null</code>，表示该参数为空。比如，某个函数接受引擎抛出的错误作为参数，如果运行过程中未出错，那么这个参数就会传入 <code>null</code>，表示未发生错误。==<code>undefined</code> 表示变量“未定义”。==</p>
<h3 id="布尔值"><a href="#布尔值" class="headerlink" title="布尔值"></a>布尔值</h3><p>布尔值代表“真”和“假”两个状态。“真”用关键字 <code>true</code> 表示，“假”用关键字 <code>false</code> 表示。==布尔值只有这两个值。==</p>
<p>下列运算符会返回布尔值：</p>
<ul>
<li>前置逻辑运算符： <code>! (Not)</code></li>
<li>相等运算符：<code>===，!==，==，!=</code></li>
<li>比较运算符：<code>&gt;，&gt;=，&lt;，&lt;=</code></li>
</ul>
<p>如果 JavaScript 预期某个位置应该是布尔值，会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为 <code>false</code>，其他值都视为 <code>true</code>。</p>
<ul>
<li><code>undefined</code></li>
<li><code>null</code></li>
<li><code>false</code></li>
<li><code>0</code></li>
<li><code>NaN</code></li>
<li><code>&quot;&quot; 或 &#39;&#39;</code>（空字符串）</li>
</ul>
<h2 id="数值"><a href="#数值" class="headerlink" title="数值"></a>数值</h2><p>JavaScript 内部，所有数字都是以 64 位浮点数形式储存，即使整数也是如此。所以，<code>1</code> 与 <code>1.0</code> 是相同的，是同一个数。由于浮点数不是精确的值，所以==涉及小数的比较和运算要特别小心。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">0.1</span> + <span class="number">0.2</span> === <span class="number">0.3</span></span><br><span class="line"><span class="comment">// false</span></span><br><span class="line"></span><br><span class="line"><span class="number">0.3</span> / <span class="number">0.1</span></span><br><span class="line"><span class="comment">// 2.9999999999999996</span></span><br><span class="line"></span><br><span class="line">(<span class="number">0.3</span> - <span class="number">0.2</span>) === (<span class="number">0.2</span> - <span class="number">0.1</span>)</span><br><span class="line"><span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<h3 id="NaN"><a href="#NaN" class="headerlink" title="NaN"></a>NaN</h3><p><code>NaN</code> 是 JavaScript 的特殊值，表示“非数字”（Not a Number），主要出现在将字符串解析成数字出错的场合。</p>
<ul>
<li>==<code>NaN</code> 不是独立的数据类型，而是一个特殊数值，它的数据类型依然属于 Number；==</li>
<li>==<code>NaN</code> 不等于任何值，包括它本身；==</li>
<li>==<code>NaN</code> 在布尔运算时被当作 <code>false</code>；==</li>
<li>==<code>NaN</code> 与任何数（包括它自己）的运算，得到的都是 <code>NaN</code>。==</li>
</ul>
<h3 id="parseInt"><a href="#parseInt" class="headerlink" title="parseInt()"></a>parseInt()</h3><p><code>parseInt</code> 全局方法用于将字符串转为整数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">parseInt</span>(<span class="string">'123'</span>) <span class="comment">// 123</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'   81'</span>) <span class="comment">// 81</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="number">1.23</span>) <span class="comment">// 1</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'1.23'</span>) <span class="comment">// 1</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'8a'</span>) <span class="comment">// 8</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'12**'</span>) <span class="comment">// 12</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'12.34'</span>) <span class="comment">// 12</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'15e2'</span>) <span class="comment">// 15</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'15px'</span>) <span class="comment">// 15</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'abc'</span>) <span class="comment">// NaN</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'.3'</span>) <span class="comment">// NaN</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">''</span>) <span class="comment">// NaN</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'+'</span>) <span class="comment">// NaN</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'+1'</span>) <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<h3 id="parseFloat"><a href="#parseFloat" class="headerlink" title="parseFloat()"></a>parseFloat()</h3><p><code>parseFloat</code> 全局方法用于将一个字符串转为浮点数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">parseFloat</span>(<span class="string">'3.14'</span>) <span class="comment">// 3.14</span></span><br><span class="line"><span class="built_in">parseFloat</span>(<span class="string">'3.14more non-digit characters'</span>) <span class="comment">// 3.14</span></span><br><span class="line"><span class="built_in">parseFloat</span>([]) <span class="comment">// NaN</span></span><br><span class="line"><span class="built_in">parseFloat</span>(<span class="string">'FF2'</span>) <span class="comment">// NaN</span></span><br><span class="line"><span class="built_in">parseFloat</span>(<span class="string">''</span>) <span class="comment">// NaN</span></span><br><span class="line"><span class="built_in">parseFloat</span>(<span class="string">''</span>) <span class="comment">// NaN（注意：parseFloat 会将空字符串转为 NaN）</span></span><br><span class="line"><span class="built_in">Number</span>(<span class="string">''</span>) <span class="comment">// 0</span></span><br><span class="line"><span class="built_in">parseFloat</span>(<span class="string">'123.45#'</span>) <span class="comment">// 123.45</span></span><br><span class="line"><span class="built_in">Number</span>(<span class="string">'123.45#'</span>) <span class="comment">// NaN</span></span><br></pre></td></tr></table></figure>

<h3 id="isNaN"><a href="#isNaN" class="headerlink" title="isNaN()"></a>isNaN()</h3><p><code>isNaN</code> 方法可以用来判断一个值是否为 <code>NaN</code>。</p>
<p>可以利用 <code>NaN</code> 为唯一不等于自身的值的这个特点，进行判断。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">myIsNaN</span>(<span class="params">value</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> value !== value;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h2><p>字符串就是零个或多个排在一起的字符，放在单引号或双引号之中。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'abc'</span></span><br><span class="line"><span class="string">"abc"</span></span><br></pre></td></tr></table></figure>


<h3 id="转义"><a href="#转义" class="headerlink" title="转义"></a>转义</h3><p>反斜杠 <code>\</code> 在字符串内有特殊含义，用来表示一些特殊字符，所以又称为转义符。</p>
<p>需要用反斜杠转义的特殊字符，主要有下面这些。</p>
<ul>
<li>\0 ：null（\u0000）</li>
<li>\b ：后退键（\u0008）</li>
<li>\f ：换页符（\u000C）</li>
<li>\n ：换行符（\u000A）</li>
<li>\r ：回车键（\u000D）</li>
<li>\t ：制表符（\u0009）</li>
<li>\v ：垂直制表符（\u000B）</li>
<li>\‘ ：单引号（\u0027）</li>
<li>\“ ：双引号（\u0022）</li>
<li>\\ ：反斜杠（\u005C）</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">'1\n2'</span>)</span><br><span class="line"><span class="comment">// 1</span></span><br><span class="line"><span class="comment">// 2</span></span><br></pre></td></tr></table></figure>


<h3 id="字符串与数组"><a href="#字符串与数组" class="headerlink" title="字符串与数组"></a>字符串与数组</h3><p>字符串可以被视为字符数组，因此可以使用数组的方括号运算符，用来返回某个位置的字符（位置编号从 <code>0</code> 开始）。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> s = <span class="string">'hello'</span>;</span><br><span class="line">s[<span class="number">0</span>] <span class="comment">// "h"</span></span><br><span class="line">s[<span class="number">1</span>] <span class="comment">// "e"</span></span><br><span class="line">s[<span class="number">4</span>] <span class="comment">// "o"</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 直接对字符串使用方括号运算符</span></span><br><span class="line"><span class="string">'hello'</span>[<span class="number">1</span>] <span class="comment">// "e"</span></span><br></pre></td></tr></table></figure>

<p>但是，==字符串与数组的相似性仅此而已。实际上，无法改变字符串之中的单个字符。==</p>
<h3 id="length-属性"><a href="#length-属性" class="headerlink" title="length 属性"></a>length 属性</h3><p><code>length</code> 属性返回字符串的长度，该属性也是无法改变的。</p>
<h2 id="对象"><a href="#对象" class="headerlink" title="对象"></a>对象</h2><p>对象就是一组“键值对”（key-value）的集合，是==一种无序的复合数据集合。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  foo: <span class="string">'Hello'</span>,</span><br><span class="line">  bar: <span class="string">'World'</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>


<h3 id="键名"><a href="#键名" class="headerlink" title="键名"></a>键名</h3><p>对象的所有==键名都是字符串==（ES6 又引入了 <code>Symbol</code> 值也可以作为键名），所以加不加引号都可以。</p>
<p>对象的属性之间用逗号分隔，最后一个属性后面可以加逗号，也可以不加。</p>
<h3 id="对象的引用"><a href="#对象的引用" class="headerlink" title="对象的引用"></a>对象的引用</h3><p>==如果不同的变量名指向同一个对象，那么它们都是这个对象的引用，也就是说指向同一个内存地址。修改其中一个变量，会影响到其他所有变量。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> o1 = &#123;&#125;;</span><br><span class="line"><span class="keyword">var</span> o2 = o1;</span><br><span class="line"></span><br><span class="line">o1.a = <span class="number">1</span>;</span><br><span class="line">o2.a <span class="comment">// 1</span></span><br><span class="line"></span><br><span class="line">o2.b = <span class="number">2</span>;</span><br><span class="line">o1.b <span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<h3 id="表达式还是语句？"><a href="#表达式还是语句？" class="headerlink" title="表达式还是语句？"></a>表达式还是语句？</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123; <span class="attr">foo</span>: <span class="number">123</span> &#125;</span><br></pre></td></tr></table></figure>


<p>JavaScript 引擎读到上面这行代码，会发现可能有两种含义。第一种可能是，这是一个表达式，表示一个包含 <code>foo</code>  属性的对象；第二种可能是，这是一个语句，表示一个代码区块，里面有一个标签 <code>foo</code>，指向表达式 <code>123</code>。</p>
<p>为了避免这种歧义，JavaScript 引擎的做法是，==如果遇到这种情况，无法确定是对象还是代码块，一律解释为代码块。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123; <span class="built_in">console</span>.log(<span class="number">123</span>) &#125; <span class="comment">// 123</span></span><br></pre></td></tr></table></figure>

<p>==如果要解释为对象，最好在大括号前加上圆括号。== 因为圆括号的里面，只能是表达式，所以确保大括号只能解释为对象。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">(&#123; <span class="attr">foo</span>: <span class="number">123</span> &#125;) <span class="comment">// 正确</span></span><br><span class="line">(&#123; <span class="built_in">console</span>.log(<span class="number">123</span>) &#125;) <span class="comment">// 报错</span></span><br></pre></td></tr></table></figure>

<h3 id="属性操作"><a href="#属性操作" class="headerlink" title="属性操作"></a>属性操作</h3><h4 id="属性读取"><a href="#属性读取" class="headerlink" title="属性读取"></a>属性读取</h4><p>读取对象的属性，有两种方法，一种是使用点运算符，还有一种是使用方括号运算符。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  p: <span class="string">'Hello World'</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">obj.p <span class="comment">// "Hello World"</span></span><br><span class="line">obj[<span class="string">'p'</span>] <span class="comment">// "Hello World"</span></span><br></pre></td></tr></table></figure>


<p>==注意，数值键名不能使用点运算符（因为会被当成小数点），只能使用方括号运算符。==</p>
<h4 id="属性赋值"><a href="#属性赋值" class="headerlink" title="属性赋值"></a>属性赋值</h4><p>点运算符和方括号运算符，不仅可以用来读取值，还可以用来赋值。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;&#125;;</span><br><span class="line"></span><br><span class="line">obj.foo = <span class="string">'Hello'</span>;</span><br><span class="line">obj[<span class="string">'bar'</span>] = <span class="string">'World'</span>;</span><br></pre></td></tr></table></figure>

<h4 id="属性的查看"><a href="#属性的查看" class="headerlink" title="属性的查看"></a>属性的查看</h4><p>查看一个对象本身的所有属性，可以使用 <code>Object.keys</code> 方法。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  key1: <span class="number">1</span>,</span><br><span class="line">  key2: <span class="number">2</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.keys(obj);   <span class="comment">// ['key1', 'key2']</span></span><br></pre></td></tr></table></figure>

<h4 id="属性的删除：delete-命令"><a href="#属性的删除：delete-命令" class="headerlink" title="属性的删除：delete 命令"></a>属性的删除：delete 命令</h4><p><code>delete</code> 命令用于删除对象的属性，删除成功后返回 <code>true</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123; <span class="attr">p</span>: <span class="number">1</span> &#125;;</span><br><span class="line"><span class="built_in">Object</span>.keys(obj) <span class="comment">// ["p"]</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">delete</span> obj.p <span class="comment">// true</span></span><br><span class="line">obj.p <span class="comment">// undefined</span></span><br><span class="line"><span class="built_in">Object</span>.keys(obj) <span class="comment">// []</span></span><br></pre></td></tr></table></figure>

<p>注意，==删除一个不存在的属性，<code>delete</code> 不报错，而且返回 <code>true</code>。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;&#125;;</span><br><span class="line"><span class="keyword">delete</span> obj.p <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h4 id="属性是否存在：in-运算符"><a href="#属性是否存在：in-运算符" class="headerlink" title="属性是否存在：in 运算符"></a>属性是否存在：in 运算符</h4><p><code>in</code> 运算符用于检查对象是否包含某个属性（注意，检查的是键名，不是键值），如果包含就返回 <code>true</code>，否则返回 <code>false</code>。它的左边是一个字符串，表示属性名，右边是一个对象。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123; <span class="attr">p</span>: <span class="number">1</span> &#125;;</span><br><span class="line"><span class="string">'p'</span> <span class="keyword">in</span> obj <span class="comment">// true</span></span><br><span class="line"><span class="string">'toString'</span> <span class="keyword">in</span> obj <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>==<code>in</code> 运算符的一个问题是，它不能识别哪些属性是对象自身的，哪些属性是继承的。== 可以使用对象的 <code>hasOwnProperty</code> 方法判断一下，是否为对象自身的属性。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;&#125;;</span><br><span class="line"><span class="keyword">if</span> (<span class="string">'toString'</span> <span class="keyword">in</span> obj) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(obj.hasOwnProperty(<span class="string">'toString'</span>)) <span class="comment">// false</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="属性的遍历：for…in-循环"><a href="#属性的遍历：for…in-循环" class="headerlink" title="属性的遍历：for…in 循环"></a>属性的遍历：for…in 循环</h4><p><code>for...in</code> 循环用来遍历一个对象的全部属性。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;<span class="attr">a</span>: <span class="number">1</span>, <span class="attr">b</span>: <span class="number">2</span>, <span class="attr">c</span>: <span class="number">3</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i <span class="keyword">in</span> obj) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'键名：'</span>, i);</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">'键值：'</span>, obj[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 键名： a</span></span><br><span class="line"><span class="comment">// 键值： 1</span></span><br><span class="line"><span class="comment">// 键名： b</span></span><br><span class="line"><span class="comment">// 键值： 2</span></span><br><span class="line"><span class="comment">// 键名： c</span></span><br><span class="line"><span class="comment">// 键值： 3</span></span><br></pre></td></tr></table></figure>

<p><code>for...in</code> 循环有两个使用注意点。</p>
<ul>
<li>==它遍历的是对象所有可遍历（enumerable）的属性，会跳过不可遍历的属性。==</li>
<li>==它不仅遍历对象自身的属性，还遍历继承的属性。==</li>
</ul>
<p>如果继承的属性是可遍历的，那么就会被 <code>for...in</code> 循环遍历到。但是，==一般情况下，都是只想遍历对象自身的属性，所以使用 <code>for...in</code>  的时候，应该结合使用 <code>hasOwnProperty</code> 方法，在循环内部判断一下，某个属性是否为对象自身的属性。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> person = &#123; <span class="attr">name</span>: <span class="string">'老张'</span> &#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> person) &#123;</span><br><span class="line">  <span class="keyword">if</span> (person.hasOwnProperty(key)) &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(key);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// name</span></span><br></pre></td></tr></table></figure>

<h2 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h2><p>函数是一段可以反复调用的代码块。函数还能接受输入的参数，不同的参数会返回不同的值。</p>
<h3 id="函数的声明"><a href="#函数的声明" class="headerlink" title="函数的声明"></a>函数的声明</h3><p>JavaScript 有三种声明函数的方法。</p>
<ul>
<li>function 命令</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">print</span>(<span class="params">s</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(s);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<ul>
<li>函数表达式</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> print = <span class="function"><span class="keyword">function</span>(<span class="params">s</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(s);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<ul>
<li>Function 构造函数（几乎不用）</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> add = <span class="keyword">new</span> <span class="built_in">Function</span>(</span><br><span class="line">  <span class="string">'x'</span>,</span><br><span class="line">  <span class="string">'y'</span>,</span><br><span class="line">  <span class="string">'return x + y'</span></span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 等同于</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">x, y</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> x + y;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>==如果同一个函数被多次声明，后面的声明就会覆盖前面的声明。==</p>
<h3 id="圆括号运算符，return-语句"><a href="#圆括号运算符，return-语句" class="headerlink" title="圆括号运算符，return 语句"></a>圆括号运算符，return 语句</h3><p>调用函数时，要使用圆括号运算符。圆括号之中，可以加入函数的参数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">x, y</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> x + y;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">add(<span class="number">1</span>, <span class="number">1</span>) <span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<p>==函数体内部的 <code>return</code> 语句，表示返回。JavaScript 引擎遇到 <code>return</code> 语句，就直接返回 <code>return</code> 后面的那个表达式的值，后面即使还有语句，也不会得到执行。== 也就是说，<code>return</code> 语句所带的那个表达式，就是函数的返回值。<code>return</code> 语句不是必需的，如果没有的话，该函数就不返回任何值，或者说返回 <code>undefined</code>。</p>
<h3 id="递归"><a href="#递归" class="headerlink" title="递归"></a>递归</h3><p>==函数可以调用自身，这就是递归。== 下面就是通过递归，计算斐波那契数列的代码。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fib</span>(<span class="params">num</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (num === <span class="number">0</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">if</span> (num === <span class="number">1</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">  <span class="keyword">return</span> fib(num - <span class="number">2</span>) + fib(num - <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">fib(<span class="number">6</span>) <span class="comment">// 8</span></span><br></pre></td></tr></table></figure>

<h3 id="函数名的提升"><a href="#函数名的提升" class="headerlink" title="函数名的提升"></a>函数名的提升</h3><p>==JavaScript 引擎将函数名视同变量名，所以采用 <code>function</code> 命令声明函数时，整个函数会像变量声明一样，被提升到代码头部。== 所以，下面的代码不会报错。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">f();</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params"></span>) </span>&#123;&#125;</span><br></pre></td></tr></table></figure>

<p>但是，如果采用赋值语句定义函数，JavaScript 就会报错。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">f();</span><br><span class="line"><span class="keyword">var</span> f = <span class="function"><span class="keyword">function</span> (<span class="params"></span>)</span>&#123;&#125;;</span><br><span class="line"><span class="comment">// TypeError: undefined is not a function</span></span><br></pre></td></tr></table></figure>

<p>上面的代码等同于下面的形式。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> f;</span><br><span class="line">f();</span><br><span class="line">f = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;&#125;;</span><br></pre></td></tr></table></figure>

<h3 id="函数的属性和方法"><a href="#函数的属性和方法" class="headerlink" title="函数的属性和方法"></a>函数的属性和方法</h3><h4 id="name"><a href="#name" class="headerlink" title="name"></a>name</h4><p>函数的 <code>name</code> 属性返回函数的名字。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f1</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line">f1.name <span class="comment">// "f1"</span></span><br></pre></td></tr></table></figure>

<h4 id="length-属性-1"><a href="#length-属性-1" class="headerlink" title="length 属性"></a>length 属性</h4><p>函数的 <code>length</code> 属性返回函数预期传入的参数个数，即函数定义之中的参数个数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params">a, b</span>) </span>&#123;&#125;</span><br><span class="line">f.length <span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<h4 id="toString-NaN"><a href="#toString-NaN" class="headerlink" title="toString()"></a>toString()</h4><p>函数的 <code>toString</code> 方法返回一个字符串，内容是函数的源码。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  a();</span><br><span class="line">  b();</span><br><span class="line">  c();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">f.toString()</span><br><span class="line"><span class="comment">// function f() &#123;</span></span><br><span class="line"><span class="comment">//  a();</span></span><br><span class="line"><span class="comment">//  b();</span></span><br><span class="line"><span class="comment">//  c();</span></span><br><span class="line"><span class="comment">// &#125;</span></span><br></pre></td></tr></table></figure>

<p>对于那些原生的函数，<code>toString()</code> 方法返回 <code>function (){[native code]}</code>。</p>
<h3 id="函数作用域"><a href="#函数作用域" class="headerlink" title="函数作用域"></a>函数作用域</h3><h4 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h4><p>作用域指的是变量存在的范围。在 ES5 的规范中，JavaScript 只有两种作用域：==一种是全局作用域，变量在整个程序中一直存在，所有地方都可以读取；另一种是函数作用域，变量只在函数内部存在。== ES6 又新增了块级作用域，本笔记不涉及。</p>
<p>对于顶层函数来说，函数外部声明的变量就是全局变量，它可以在函数内部读取。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> v = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(v);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">f()</span><br><span class="line"><span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<p>在函数内部定义的变量，外部无法读取，称为“局部变量”。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="keyword">var</span> v = <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">v <span class="comment">// ReferenceError: v is not defined</span></span><br></pre></td></tr></table></figure>

<p>函数内部定义的变量，会在该作用域内覆盖同名全局变量。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> v = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">  <span class="keyword">var</span> v = <span class="number">2</span>;</span><br><span class="line">  <span class="built_in">console</span>.log(v);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">f() <span class="comment">// 2</span></span><br><span class="line">v <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<p>对于 <code>var</code> 命令来说，局部变量只能在函数内部声明，在其他区块中声明，一律都是全局变量。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">  <span class="keyword">var</span> x = <span class="number">5</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">console</span>.log(x);  <span class="comment">// 5</span></span><br></pre></td></tr></table></figure>

<h4 id="函数内部的变量提升"><a href="#函数内部的变量提升" class="headerlink" title="函数内部的变量提升"></a>函数内部的变量提升</h4><p>与全局作用域一样，函数作用域内部也会产生“变量提升”现象。<code>var</code> 命令声明的变量，不管在什么位置，变量声明都会被提升到函数体的头部。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">x</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">if</span> (x &gt; <span class="number">100</span>) &#123;</span><br><span class="line">    <span class="keyword">var</span> tmp = x - <span class="number">100</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 等同于</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params">x</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> tmp;</span><br><span class="line">  <span class="keyword">if</span> (x &gt; <span class="number">100</span>) &#123;</span><br><span class="line">    tmp = x - <span class="number">100</span>;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="函数本身的作用域"><a href="#函数本身的作用域" class="headerlink" title="函数本身的作用域"></a>函数本身的作用域</h4><p>函数本身也是一个值，也有自己的作用域。==它的作用域与变量一样，就是其声明时所在的作用域，与其运行时所在的作用域无关。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">var</span> x = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(a);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> a = <span class="number">2</span>;</span><br><span class="line">  x();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">f() <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<h3 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h3><h4 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h4><p>函数运行的时候，有时需要提供外部数据，不同的外部数据会得到不同的结果，这种外部数据就叫参数。</p>
<p>函数参数不是必需的，JavaScript 允许省略参数。但是，没有办法只省略靠前的参数，而保留靠后的参数。如果一定要省略靠前的参数，只有显式传入 <code>undefined</code>。</p>
<h4 id="传递方式"><a href="#传递方式" class="headerlink" title="传递方式"></a>传递方式</h4><p>函数参数如果是原始类型的值（数值、字符串、布尔值），传递方式是传值传递。这意味着，在函数体内修改参数值，不会影响到函数外部。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> p = <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params">p</span>) </span>&#123;</span><br><span class="line">  p = <span class="number">3</span>;</span><br><span class="line">&#125;</span><br><span class="line">f(p);</span><br><span class="line"></span><br><span class="line">p <span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<h3 id="闭包"><a href="#闭包" class="headerlink" title="闭包"></a>闭包</h3><p>理解闭包，首先必须理解变量作用域。前面提到，JavaScript 有两种作用域：==全局作用域和函数作用域。函数内部可以直接读取全局变量，函数外部无法读取函数内部声明的变量。==</p>
<p>如果需要得到函数内的局部变量。正常情况下，这是办不到的，只有通过变通方法才能实现。那就是在函数的内部，再定义一个函数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> n = <span class="number">999</span>;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">f2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(n);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> f2;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> result = f1();</span><br><span class="line">result(); <span class="comment">// 999</span></span><br></pre></td></tr></table></figure>

<p>由于在 JavaScript 语言中，只有函数内部的子函数才能读取内部变量，因此可以把闭包简单理解成“定义在一个函数内部的函数”。</p>
<p>闭包的用处有：</p>
<ul>
<li>可以读取函数内部的变量</li>
<li>让这些变量始终保持在内存中，即闭包可以使得它诞生环境一直存在</li>
<li>封装对象的私有属性和私有方法</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> _age;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">setAge</span>(<span class="params">n</span>) </span>&#123;</span><br><span class="line">    _age = n;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">getAge</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> _age;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    name: name,</span><br><span class="line">    getAge: getAge,</span><br><span class="line">    setAge: setAge</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> p1 = Person(<span class="string">'张三'</span>);</span><br><span class="line">p1.setAge(<span class="number">25</span>);</span><br><span class="line">p1.getAge() <span class="comment">// 25</span></span><br></pre></td></tr></table></figure>

<p>==外层函数每次运行，都会生成一个新的闭包，而这个闭包又会保留外层函数的内部变量，所以内存消耗很大。== 因此不能滥用闭包，否则会造成网页的性能问题。</p>
<h3 id="立即调用的函数表达式（IIFE）"><a href="#立即调用的函数表达式（IIFE）" class="headerlink" title="立即调用的函数表达式（IIFE）"></a>立即调用的函数表达式（IIFE）</h3><p>在 JavaScript 中，圆括号 <code>()</code> 是一种运算符，跟在函数名之后，表示调用该函数。比如，<code>print()</code> 就表示调用 <code>print</code> 函数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; <span class="comment">/* code */</span> &#125;());</span><br><span class="line"><span class="comment">// 或者</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; <span class="comment">/* code */</span> &#125;)();</span><br></pre></td></tr></table></figure>

<p>==注意，上面两种写法最后的分号都是必须的。如果省略分号，遇到连着两个 IIFE，可能就会报错。==</p>
<p>通常情况下，只对匿名函数使用这种“立即执行的函数表达式”。</p>
<p>它的目的有两个：</p>
<ul>
<li>一是不必为函数命名，避免了污染全局变量；</li>
<li>二是 IIFE 内部形成了一个单独的作用域，可以封装一些外部无法读取的私有变量。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 写法一</span></span><br><span class="line"><span class="keyword">var</span> tmp = newData;</span><br><span class="line">processData(tmp);</span><br><span class="line">storeData(tmp);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 写法二（推荐：因为完全避免了污染全局变量）</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> tmp = newData;</span><br><span class="line">  processData(tmp);</span><br><span class="line">  storeData(tmp);</span><br><span class="line">&#125;());</span><br></pre></td></tr></table></figure>

<hr>
<h1 id="变量的声明"><a href="#变量的声明" class="headerlink" title="变量的声明"></a>变量的声明</h1><h2 id="ES-5-1"><a href="#ES-5-1" class="headerlink" title="ES 5.1"></a>ES 5.1</h2><ul>
<li><code>var</code></li>
<li><code>function</code></li>
</ul>
<h2 id="ES-6"><a href="#ES-6" class="headerlink" title="ES 6"></a>ES 6</h2><ul>
<li><code>var</code></li>
<li><code>function</code></li>
<li><code>const</code></li>
<li><code>let</code></li>
<li><code>import</code></li>
<li><code>class</code></li>
</ul>
<hr>
<h1 id="运算符"><a href="#运算符" class="headerlink" title="运算符"></a>运算符</h1><h2 id="取反运算符（-）"><a href="#取反运算符（-）" class="headerlink" title="取反运算符（!）"></a>取反运算符（!）</h2><p>将布尔值变为反向值，==以下 6 个值取反后为 <code>true</code>，其他值都为 <code>false</code>。==</p>
<ul>
<li><code>undefined</code></li>
<li><code>null</code></li>
<li><code>NaN</code></li>
<li><code>0</code></li>
<li><code>false</code></li>
<li><code>空字符串(&#39;&#39;)</code></li>
</ul>
<p>注意：==空数组 [ ]、空对象 { } 这些转为布尔值都为 true，取反为 false。==</p>
<h2 id="或运算符（a-b）"><a href="#或运算符（a-b）" class="headerlink" title="或运算符（a || b）"></a>或运算符（a || b）</h2><p>如果 a 返回的布尔值为 <code>true</code>，返回 a 的值，不再对 b 求值；如果 a 返回的布尔值为 <code>false</code>，直接返回 b 的值。（注意：==这里返回的是 a 或者 b 表达式的结果值，而不是布尔值。==）</p>
<h2 id="且运算符（a-amp-amp-b）"><a href="#且运算符（a-amp-amp-b）" class="headerlink" title="且运算符（a &amp;&amp; b）"></a>且运算符（a &amp;&amp; b）</h2><p>如果 a 返回的布尔值为 <code>true</code>，则返回 b 的值，如果 a 返回的布尔值是 <code>false</code>，则直接返回 a 的值。（注意：==这里返回的是 a 或者 b 表达式的结果值，而不是布尔值。==）</p>
<h2 id="和"><a href="#和" class="headerlink" title="== 和 ==="></a>== 和 ===</h2><ul>
<li><code>==</code> 比较两个值是否相等，类型可以不同。</li>
<li><code>===</code> 比较两个值是否为“同一个值”，类型必须相同。</li>
</ul>
<h2 id="三元条件运算符（a-b-c）"><a href="#三元条件运算符（a-b-c）" class="headerlink" title="三元条件运算符（a ? b : c）"></a>三元条件运算符（a ? b : c）</h2><p>如果第一个表达式 <code>a</code> 的布尔值为 <code>true</code>，则返回 <code>b</code> 表达式的值，否则返回 <code>c</code> 表达式的值。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a ? b : c <span class="comment">// a 如果返回 true ，则执行 b ，否则执行 c</span></span><br></pre></td></tr></table></figure>

<h2 id="自增和自减"><a href="#自增和自减" class="headerlink" title="自增和自减"></a>自增和自减</h2><p>将运算符首先转为数值，然后加上 <code>1</code> 或者减去 <code>1</code>。它们会修改原始变量。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> x = <span class="number">1</span>;</span><br><span class="line">++x <span class="comment">// 2</span></span><br><span class="line">x <span class="comment">// 2</span></span><br><span class="line"></span><br><span class="line">--x <span class="comment">// 1</span></span><br><span class="line">x <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<p>放在变量之后，会先返回变量操作前的值，再进行自增/自减操作；放在变量之前，会先进行自增/自减操作，再返回变量操作后的值。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> x = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">var</span> y = <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">x++ <span class="comment">// 1</span></span><br><span class="line">++y <span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<hr>
<h1 id="数据类型转换"><a href="#数据类型转换" class="headerlink" title="数据类型转换"></a>数据类型转换</h1><h2 id="强制转换"><a href="#强制转换" class="headerlink" title="强制转换"></a>强制转换</h2><ul>
<li><code>Number()</code></li>
<li><code>String()</code></li>
<li><code>Boolean()</code></li>
</ul>
<h2 id="自动转换"><a href="#自动转换" class="headerlink" title="自动转换"></a>自动转换</h2><p>自动转换具有不确定性，而且不易除错，==建议在预期为布尔值、数值、字符串的地方，全部使用 Boolean、Number 和 String 函数进行显式转换。==</p>
<h3 id="自动转换为布尔值"><a href="#自动转换为布尔值" class="headerlink" title="自动转换为布尔值"></a>自动转换为布尔值</h3><p>除了 <code>undefined、null、+0、0</code> 或者 <code>-0、NaN</code>、空字符串 <code>&quot;&quot;</code>，其它都会自动转换为 <code>true</code>。</p>
<h3 id="自动转换为字符串"><a href="#自动转换为字符串" class="headerlink" title="自动转换为字符串"></a>自动转换为字符串</h3><p>字符串加法运算时候，当一个值为字符串，另一个值为非字符串，则后者会自动转换为字符串。</p>
<h3 id="自动转换为数值"><a href="#自动转换为数值" class="headerlink" title="自动转换为数值"></a>自动转换为数值</h3><p>除了加法运算符（<code>+</code>）有可能会运算子转化为字符串，其它运算符都会把运算子自动转换为数值。</p>
<hr>
<h1 id="String-常见用法"><a href="#String-常见用法" class="headerlink" title="String 常见用法"></a>String 常见用法</h1><h2 id="String-prototype-slice"><a href="#String-prototype-slice" class="headerlink" title="String.prototype.slice()"></a>String.prototype.slice()</h2><p>==用于从原来字符串中提取字符串并返回，不会改变原来的字符串。== 第一个参数是字符串开始位置，第二个参数是字符串结束位置（不包含该位置）。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'JavaScript'</span>.slice(<span class="number">0</span>, <span class="number">4</span>) <span class="comment">// "Java"</span></span><br></pre></td></tr></table></figure>

<h2 id="String-prototype-substring-、String-prototype-substr"><a href="#String-prototype-substring-、String-prototype-substr" class="headerlink" title="String.prototype.substring()、String.prototype.substr()"></a>String.prototype.substring()、String.prototype.substr()</h2><p>用法基本和 <code>String.prototype.slice()</code> 一样的，一般建议用 <code>slice</code> 方法即可。</p>
<h2 id="String-prototype-indexOf-、String-prototype-lastIndexOf"><a href="#String-prototype-indexOf-、String-prototype-lastIndexOf" class="headerlink" title="String.prototype.indexOf()、String.prototype.lastIndexOf()"></a>String.prototype.indexOf()、String.prototype.lastIndexOf()</h2><p><code>indexOf</code> 方法用于确定一个字符串在另一个字符串中第一次出现的位置，返回结果是匹配开始的位置。如果返回 -1 就表示不匹配。 <code>lastIndexOf</code> 用法和 <code>indexOf</code> 基本一样，区别在于从字符串的尾部，向前查找。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'hello world'</span>.indexOf(<span class="string">'o'</span>) <span class="comment">// 4</span></span><br><span class="line"><span class="string">'JavaScript'</span>.indexOf(<span class="string">'script'</span>) <span class="comment">// -1</span></span><br></pre></td></tr></table></figure>

<p>支持第二个参数，表示从该位置向后查询。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'hello world'</span>.indexOf(<span class="string">'o'</span>, <span class="number">6</span>) <span class="comment">// 7</span></span><br></pre></td></tr></table></figure>

<h2 id="String-prototype-trim"><a href="#String-prototype-trim" class="headerlink" title="String.prototype.trim()"></a>String.prototype.trim()</h2><p>去除字符串两端的空格，返回新的字符串，==不改变原字符串。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'  hello world  '</span>.trim() <span class="comment">// "hello world"</span></span><br></pre></td></tr></table></figure>

<h2 id="String-prototype-toLowerCase-、toUpperCase"><a href="#String-prototype-toLowerCase-、toUpperCase" class="headerlink" title="String.prototype.toLowerCase()、toUpperCase()"></a>String.prototype.toLowerCase()、toUpperCase()</h2><p><code>toLowerCase</code> 方法用于将一个字符串全部转为小写，<code>toUpperCase</code> 则是全部转为大写。==它们都返回一个新字符串，不改变原字符串。==</p>
<h2 id="String-prototype-match"><a href="#String-prototype-match" class="headerlink" title="String.prototype.match()"></a>String.prototype.match()</h2><p>用于确定字符串是否匹配某个子字符串，返回一个数组，成员为匹配的第一个字符串。如果没有找到，返回 <code>null</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'gkasjdlfs'</span>.match(<span class="string">'s'</span>) <span class="comment">// ["s", index: 3, input: "gkasjdlfs", groups: undefined]</span></span><br><span class="line"><span class="string">'guopengsong'</span>.match(<span class="string">'d'</span>) <span class="comment">// null</span></span><br></pre></td></tr></table></figure>

<h2 id="String-prorotype-search"><a href="#String-prorotype-search" class="headerlink" title="String.prorotype.search()"></a>String.prorotype.search()</h2><p><code>search</code> 方法的用法基本等同于 <code>match</code>，但是返回的是匹配的第一个索引位置。如果没有找到匹配，返回 <code>-1</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'asdfghjkl'</span>.search(<span class="string">'d'</span>) <span class="comment">// 2</span></span><br><span class="line"><span class="string">'asdfsdf'</span>.search(<span class="string">'fgse'</span>) <span class="comment">// -1</span></span><br></pre></td></tr></table></figure>

<h2 id="String-prototype-replace"><a href="#String-prototype-replace" class="headerlink" title="String.prototype.replace()"></a>String.prototype.replace()</h2><p><code>replace</code> 方法用于替换匹配的字符串，一般情况下只替换第一个匹配（除非使用带有 <code>g</code> 修饰符的正则表达式）。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'asdfsadf'</span>.replace(<span class="string">'a'</span>,<span class="string">'---'</span>) <span class="comment">// "---sdfsadf"</span></span><br></pre></td></tr></table></figure>

<h2 id="String-prototype-split"><a href="#String-prototype-split" class="headerlink" title="String.prototype.split()"></a>String.prototype.split()</h2><p>==<code>split</code> 方法按照给定规则分割字符串，返回一个由分割出来的子字符串组成的数组。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'a|b|c'</span>.split(<span class="string">'|'</span>) <span class="comment">// ['a','b','c']</span></span><br></pre></td></tr></table></figure>

<hr>
<h1 id="Number-常见用法"><a href="#Number-常见用法" class="headerlink" title="Number 常见用法"></a>Number 常见用法</h1><h2 id="Number-prototype-toString"><a href="#Number-prototype-toString" class="headerlink" title="Number.prototype.toString()"></a>Number.prototype.toString()</h2><p>将一个数值转化为字符串形式。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(<span class="number">10</span>).toString() <span class="comment">// '10'</span></span><br></pre></td></tr></table></figure>

<h2 id="Number-prototype-toFiexd"><a href="#Number-prototype-toFiexd" class="headerlink" title="Number.prototype.toFiexd()"></a>Number.prototype.toFiexd()</h2><p><code>toFiexd()</code> 方法先将一个数值转化为指定位数的小数，然后返回这个小数对应的字符串。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">10.005</span>.toFixed(<span class="number">2</span>) <span class="comment">// "10.01"</span></span><br></pre></td></tr></table></figure>

<h2 id="全局方法-parseInt"><a href="#全局方法-parseInt" class="headerlink" title="全局方法 parseInt()"></a>全局方法 parseInt()</h2><p>用于将字符串转为整数，会删除小数部分。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">parseInt</span>(<span class="string">'123'</span>) <span class="comment">// 123</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">'3.4'</span>) <span class="comment">// 3</span></span><br></pre></td></tr></table></figure>

<h2 id="全局方法-parseFloat"><a href="#全局方法-parseFloat" class="headerlink" title="全局方法 parseFloat()"></a>全局方法 parseFloat()</h2><p><code>parseFloat()</code> 方法用于将一个字符串转为浮点数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">parseFloat</span>(<span class="string">'3.244'</span>) <span class="comment">// 3.244</span></span><br></pre></td></tr></table></figure>

<h2 id="NaN、全局方法-isNaN"><a href="#NaN、全局方法-isNaN" class="headerlink" title="NaN、全局方法 isNaN()"></a>NaN、全局方法 isNaN()</h2><p><code>NaN</code> 特殊值，表示“非数值”，出现在将字符串解析成数值出错的场合。</p>
<p><code>isNaN</code> 方法可以用来判断一个值是否为 <code>NaN</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">isNaN</span>(<span class="literal">NaN</span>) <span class="comment">// true</span></span><br><span class="line"><span class="built_in">isNaN</span>(<span class="number">213</span>) <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<hr>
<h1 id="Array-常见用法"><a href="#Array-常见用法" class="headerlink" title="Array 常见用法"></a>Array 常见用法</h1><p><code>Array</code> 是 JavaScript 的原生对象，同时也是一个构造函数，可以用它生成新的数组。</p>
<h2 id="Array-isArray"><a href="#Array-isArray" class="headerlink" title="Array.isArray()"></a>Array.isArray()</h2><p>返回一个布尔值，表示参数是否为数组，可以弥补 <code>typeof</code> 运算符的不足。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>];</span><br><span class="line"><span class="keyword">typeof</span> arr <span class="comment">// 'object'</span></span><br><span class="line"><span class="built_in">Array</span>.isArray(arr) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h2 id="push"><a href="#push" class="headerlink" title="push()"></a>push()</h2><p>==<code>push</code> 方法用于在数组的末端添加一个或者多个元素，并且返回新元素后的数组长度。注意，该方法会改变原数组。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = [];</span><br><span class="line">arr.push(<span class="number">3</span>) <span class="comment">// 1</span></span><br><span class="line">arr.push(<span class="string">'a'</span>,<span class="string">'b'</span>) <span class="comment">// 3</span></span><br><span class="line">arr <span class="comment">// [3,'a','b']</span></span><br></pre></td></tr></table></figure>

<h2 id="pop"><a href="#pop" class="headerlink" title="pop()"></a>pop()</h2><p>==<code>pop</code> 方法用于删除数组的最后一个元素，并且返回该元素。注意，该方法会改变原数组。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>];</span><br><span class="line">arr.pop() <span class="comment">// 'c'</span></span><br><span class="line">arr <span class="comment">// ['a','b']</span></span><br></pre></td></tr></table></figure>


<h2 id="shift"><a href="#shift" class="headerlink" title="shift()"></a>shift()</h2><p>==<code>shift</code> 方法用于删除数组的第一个元素，并返回该元素。注意，该方法会改变原数组。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>];</span><br><span class="line">arr.shift() <span class="comment">// 'a'</span></span><br><span class="line">a <span class="comment">// ['b','c']</span></span><br></pre></td></tr></table></figure>

<h2 id="unshift"><a href="#unshift" class="headerlink" title="unshift()"></a>unshift()</h2><p>==<code>unshift</code> 方法用于在数组的第一个位置添加元素，并返回添加新元素后的数组长度。注意，该方法会改变原数组。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>];</span><br><span class="line"></span><br><span class="line">a.unshift(<span class="string">'x'</span>); <span class="comment">// 4</span></span><br><span class="line"></span><br><span class="line">a <span class="comment">// ['x','a','b','c']</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> arr = [<span class="string">'c'</span>,<span class="string">'d'</span>];</span><br><span class="line">arr.unshift(<span class="string">'a'</span>,<span class="string">'b'</span>) <span class="comment">// 4</span></span><br><span class="line">arr <span class="comment">// ['a','b','c','d']</span></span><br></pre></td></tr></table></figure>

<h2 id="join"><a href="#join" class="headerlink" title="join()"></a>join()</h2><p><code>join</code> 方法以指定参数作为分隔符，将所有数组成员连接为一个字符串返回。如果不提供参数，默认用逗号分隔。==该方法不改变原数组。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>]</span><br><span class="line"></span><br><span class="line">a.join(<span class="string">'--'</span>) <span class="comment">// 'a--b--c'</span></span><br></pre></td></tr></table></figure>

<h2 id="concat"><a href="#concat" class="headerlink" title="concat()"></a>concat()</h2><p><code>concat</code> 方法用于多个数组的合并。它将新数组的成员，添加到原数组成员的后部，然后返回一个新数组，不改变原数组。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>]</span><br><span class="line"><span class="keyword">var</span> b = [<span class="string">'c'</span>,<span class="string">'d'</span>]</span><br><span class="line"></span><br><span class="line">a.concat(b) <span class="comment">// ['a','b','c','d']</span></span><br></pre></td></tr></table></figure>

<h2 id="slice"><a href="#slice" class="headerlink" title="slice()"></a>slice()</h2><p><code>slice</code> 方法用户提取目标数组中的一部分，==返回一个新数组，原数组不变。==</p>
<p>它第一个参数为起始位置（从0开始），第二个参数为终止位置（包含该元素本身）。如果第二个参数省略，则一直返回到数组最后一个成员。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>];</span><br><span class="line"></span><br><span class="line">a.slice(<span class="number">1</span>,<span class="number">3</span>) <span class="comment">// ['b','c']</span></span><br></pre></td></tr></table></figure>

<h2 id="splice"><a href="#splice" class="headerlink" title="splice()"></a>splice()</h2><p><code>splice</code> 方法用于删除原数组中的一部分成员，并且可以在删除的位置添加新的数组成员，返回值是被删除的元素，该方法会改变原数组。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">arr.splice(start,count,addElement1,addElement2,...)</span><br></pre></td></tr></table></figure>

<p>第一个参数是删除的起始位置（从0开始），第二个参数是被删除的元素个数，后面的参数为要插入数组的新元素。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>]</span><br><span class="line"></span><br><span class="line">a.splice(<span class="number">1</span>,<span class="number">2</span>,<span class="string">'e'</span>,<span class="string">'f'</span>) <span class="comment">// ['b','c']</span></span><br><span class="line"></span><br><span class="line">a <span class="comment">// ['a','e','f','d']</span></span><br></pre></td></tr></table></figure>

<h2 id="indexOf-、lastIndexOf"><a href="#indexOf-、lastIndexOf" class="headerlink" title="indexOf()、lastIndexOf()"></a>indexOf()、lastIndexOf()</h2><p><code>indexOf</code> 方法返回给定元素在数组中第一次出现的位置，如果没有出现则返回 <code>-1</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>]</span><br><span class="line"></span><br><span class="line">a.indexOf(<span class="string">'b'</span>) <span class="comment">// 1</span></span><br><span class="line">a.indexOf(<span class="string">'x'</span>) <span class="comment">// -1</span></span><br></pre></td></tr></table></figure>

<p>可以接受第二个参数，表示搜索的开始位置。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>]</span><br><span class="line"></span><br><span class="line">a.indexOf(<span class="string">'b'</span>,<span class="number">2</span>) <span class="comment">// -1</span></span><br></pre></td></tr></table></figure>

<p><code>lastIndexOf</code> 方法返回给定元素在数组中最后一次出现的次数，如果没有出现则返回 <code>-1</code>。具体用法和 <code>indexOf</code> 相似。</p>
<h2 id="map"><a href="#map" class="headerlink" title="map()"></a>map()</h2><p><code>map</code> 方法将数组的所有成员依次传入函数参数，然后把每一次执行结果组成一个新数组返回。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>]</span><br><span class="line"></span><br><span class="line">a.map(<span class="function"><span class="keyword">function</span>(<span class="params">elem,index,arr</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> elem +<span class="string">'-'</span>;</span><br><span class="line">&#125;) <span class="comment">// ['a-','b-','c-','d-']</span></span><br><span class="line"></span><br><span class="line">a <span class="comment">// ['a','b','c','d']</span></span><br></pre></td></tr></table></figure>

<p><code>map</code> 方法的回调函数有三个参数，<code>elem</code> 为当前成员的值，<code>index</code> 为当前成员的索引位置，<code>arr</code> 为原数组 <code>a</code> 。</p>
<h2 id="forEach"><a href="#forEach" class="headerlink" title="forEach()"></a>forEach()</h2><p><code>forEach</code> 方法与 <code>map</code> 方法很像，也是对数组的所有成员依次执行参数函数。但是，==<code>forEach</code> 方法不返回值，只用来操作数据。如果数组遍历的目的是为了得到返回值，那么使用 <code>map</code> 方法，否则使用 <code>forEach</code> 方法。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>]</span><br><span class="line"></span><br><span class="line">a.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">elem,index,arr</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> elem+<span class="string">'-'</span>;</span><br><span class="line">&#125;) <span class="comment">// undefind(无返回值)</span></span><br><span class="line"></span><br><span class="line">a <span class="comment">// ['a','b','c','d']</span></span><br></pre></td></tr></table></figure>

<h2 id="filter"><a href="#filter" class="headerlink" title="filter()"></a>filter()</h2><p><code>filter</code> 方法用于过滤数组成员，满足条件的成员数组组成一个新的数组返回。</p>
<p>它的参数是一个函数，所有数组依次执行该函数，返回结果为 <code>true</code> 的成员组成一个新数组返回。==该方法不改变原数组。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="number">2</span>,<span class="number">3</span>,<span class="number">5</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">1</span>,<span class="number">4</span>,<span class="number">6</span>];</span><br><span class="line"></span><br><span class="line">a.filter(<span class="function"><span class="keyword">function</span>(<span class="params">v</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">return</span> v&gt;<span class="number">2</span>;</span><br><span class="line">&#125;) <span class="comment">// [3, 5, 3, 4, 6]</span></span><br><span class="line"></span><br><span class="line">a <span class="comment">// [2,3,5,3,2,1,4,6]</span></span><br></pre></td></tr></table></figure>

<h2 id="in-运算符、for-…-in-循环"><a href="#in-运算符、for-…-in-循环" class="headerlink" title="in 运算符、for … in 循环"></a>in 运算符、for … in 循环</h2><p>因为数组属于特殊的对象，所以也可以使用对象的 <code>in</code> 运算符，和 <code>for ... in</code> 循环。</p>
<h2 id="数组的遍历"><a href="#数组的遍历" class="headerlink" title="数组的遍历"></a>数组的遍历</h2><p>数组的遍历可以使用 <code>for</code> 循环或者 <code>while</code> 循环。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>]</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">var</span> i = <span class="number">0</span> ; i &lt; a.length ; i++)&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(a[i])</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="类数组对象"><a href="#类数组对象" class="headerlink" title="类数组对象"></a>类数组对象</h2><p>如果一个对象的所有键名都是正数或零，并且拥有 <code>length</code> 属性，那么这个对象就很像数组，语法上成为“类似数组的对象”。</p>
<p>==典型的“类似数组对象”有函数的 <code>arguments</code> 对象，以及大多数的 <code>DOM</code> 元素集，还有字符串。==</p>
<p>==数组的 <code>slice</code> 方法可以将“类似数组的对象”转换为真正的数组。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = <span class="built_in">Array</span>.prototype.slice.call(arrayLike);</span><br></pre></td></tr></table></figure>

<hr>
<h1 id="Object-常见用法"><a href="#Object-常见用法" class="headerlink" title="Object 常见用法"></a>Object 常见用法</h1><p>==对象所有的键名都是字符串（ES6 又引入了 <code>Symbol</code> 值也可以作为键名），所以加不加引号都可以。==</p>
<p>属性的读取、操作可以使用点或者中括号运算符操作。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> foo = <span class="string">'bar'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  foo: <span class="number">1</span>,</span><br><span class="line">  bar: <span class="number">2</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">obj.foo  <span class="comment">// 1</span></span><br><span class="line">obj[foo]  <span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<h2 id="delete-命令"><a href="#delete-命令" class="headerlink" title="delete 命令"></a>delete 命令</h2><p><code>delete</code> 命令用于删除对象的属性，删除成功后返回 <code>true</code>。==<code>delete</code>  命令只能删除对象本身的属性，无法删除继承的属性。==</p>
<h2 id="in-运算符"><a href="#in-运算符" class="headerlink" title="in 运算符"></a>in 运算符</h2><p><code>in</code> 运算符用于检查对象是否包含某个属性（注意，==检查的是键名而不是键值==），如果包含返回 <code>true</code>，否则返回 <code>false</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">    p:<span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="string">'p'</span> <span class="keyword">in</span> obj <span class="comment">// true（自身属性）</span></span><br><span class="line"><span class="string">'toString'</span> <span class="keyword">in</span> obj <span class="comment">//ture（继承属性）</span></span><br></pre></td></tr></table></figure>

<p>==<code>in</code> 运算符有个问题，它不能识别那些属性是自身的，哪些属性是继承的。==</p>
<p>==可以使用对象的 <code>hasOwnProperty</code> 方法判断一下，是否为对象自身的属性。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="string">'toString'</span> <span class="keyword">in</span> obj) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(obj.hasOwnProperty(<span class="string">'toString'</span>)) <span class="comment">// false</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<h2 id="for-…-in-循环"><a href="#for-…-in-循环" class="headerlink" title="for … in 循环"></a>for … in 循环</h2><p><code>for ... in</code> 循环用来遍历一个对象的所有属性。</p>
<p>有两个点需要注意：</p>
<ul>
<li>它遍历的是对象所有可遍历的属性，会跳过不可遍历的属性。</li>
<li>它不仅遍历对象自身的属性，还遍历继承的属性。</li>
</ul>
<p>==一般情况下，都是只想遍历对象的自身属性，所以使用 <code>for ... in</code> 的时候，应该结合使用 <code>hasOwnProperty</code> 方法，在循环内部判断一下，某个属性是否为对象的自身属性。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> person = &#123;<span class="attr">name</span>:<span class="string">'张三'</span>&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">var</span> key <span class="keyword">in</span> person)&#123;</span><br><span class="line">    <span class="keyword">if</span>(person.hasOwnProperty(key))&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(key);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// name</span></span><br></pre></td></tr></table></figure>

<h2 id="Object-keys-、Object-getOwnPropertyNames"><a href="#Object-keys-、Object-getOwnPropertyNames" class="headerlink" title="Object.keys()、Object.getOwnPropertyNames()"></a>Object.keys()、Object.getOwnPropertyNames()</h2><p>==<code>Object.keys</code> 方法的参数是一个对象，返回一个数组。该数组的成员都是该对象自身的（而不是继承的）所有属性名。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  p1: <span class="number">123</span>,</span><br><span class="line">  p2: <span class="number">456</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.keys(obj) <span class="comment">// ["p1", "p2"]</span></span><br></pre></td></tr></table></figure>

<p>==<code>Object.getOwnPropertyNames</code> 方法与 <code>Object.keys</code> 类似，也是接受一个对象作为参数，返回一个数组，包含了该对象自身的（而不是继承的）所有属性名。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;</span><br><span class="line">  p1: <span class="number">123</span>,</span><br><span class="line">  p2: <span class="number">456</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.getOwnPropertyNames(obj) <span class="comment">// ["p1", "p2"]</span></span><br></pre></td></tr></table></figure>

<p>一般来说，两个方法返回结果是一样的，只有涉及不可枚举属性时，才会不一样，==<code>Object.keys</code> 方法只返回可枚举的属性，<code>Object.getOwnPropertyNames</code> 方法还返回不可枚举属性名。==</p>
<h2 id="toString-应用：判断数据类型"><a href="#toString-应用：判断数据类型" class="headerlink" title="toString()应用：判断数据类型"></a>toString()应用：判断数据类型</h2><p><code>Object.prototype.toString</code> 方法返回对象的类型字符串，可以用来判断一个值的类型。</p>
<p>==由于实例对象可能会自定义 <code>toString</code> 方法，覆盖掉 <code>Object.prototype.toString</code> 方法，所以为了得到类型字符串，最好直接使用 <code>Object.prototype.toString</code> 方法。==</p>
<p>==通过函数 <code>call</code> 方法，可以在任意值上调用这个方法，来判断数据类型。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Object</span>.prototype.toString.call(value)</span><br></pre></td></tr></table></figure>


<h2 id="Object-prototype-hasOwnProperty"><a href="#Object-prototype-hasOwnProperty" class="headerlink" title="Object.prototype.hasOwnProperty()"></a>Object.prototype.hasOwnProperty()</h2><p>==<code>Object.prototype.hasOwnProperty</code>  方法接受一个字符串作为参数，返回一个布尔值，表示该实例对象自身是否具有该属性。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;<span class="attr">a</span>:<span class="number">1</span>&#125;</span><br><span class="line"></span><br><span class="line">obj.hasOwnProperty(<span class="string">'a'</span>) <span class="comment">// true</span></span><br><span class="line">obj.hasOwnProperty(<span class="string">'toString'</span>) <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<hr>
<h1 id="Math-用法"><a href="#Math-用法" class="headerlink" title="Math 用法"></a>Math 用法</h1><h2 id="Math-abs"><a href="#Math-abs" class="headerlink" title="Math.abs()"></a>Math.abs()</h2><p><code>Math.abs</code> 方法返回参数的绝对值。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Math</span>.abs(<span class="number">1</span>) <span class="comment">// 1</span></span><br><span class="line"><span class="built_in">Math</span>.abs(<span class="number">-1</span>) <span class="comment">// -1</span></span><br></pre></td></tr></table></figure>

<h2 id="Math-max-、Math-min"><a href="#Math-max-、Math-min" class="headerlink" title="Math.max()、Math.min()"></a>Math.max()、Math.min()</h2><p><code>Math.max</code> 方法返回参数中最大的那个值，<code>Math.min</code> 方法返回参数中最小的那个值。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Math</span>.max(<span class="number">2</span>,<span class="number">1</span>,<span class="number">4</span>) <span class="comment">// 4</span></span><br><span class="line"><span class="built_in">Math</span>.min(<span class="number">-2</span>,<span class="number">4</span>,<span class="number">1</span>) <span class="comment">// -2</span></span><br></pre></td></tr></table></figure>

<h2 id="Math-floor-、Math-ceil"><a href="#Math-floor-、Math-ceil" class="headerlink" title="Math.floor()、Math.ceil()"></a>Math.floor()、Math.ceil()</h2><p><code>Math.floor</code> 方法返回小于参数值的最大整数（地板值）。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Math</span>.flor(<span class="number">3.9</span>) <span class="comment">// 3</span></span><br></pre></td></tr></table></figure>

<p><code>Math.ceil</code> 方法返回大于单数值的最小整数（天花板值）。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Math</span>.ceil(<span class="number">1.1</span>) <span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<h2 id="Math-round"><a href="#Math-round" class="headerlink" title="Math.round()"></a>Math.round()</h2><p><code>Math.round</code> 方法用于四舍五入。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Math</span>.round(<span class="number">0.1</span>) <span class="comment">// 0</span></span><br><span class="line"><span class="built_in">Math</span>.round(<span class="number">4.5</span>) <span class="comment">// 5</span></span><br></pre></td></tr></table></figure>

<h2 id="Math-random"><a href="#Math-random" class="headerlink" title="Math.random()"></a>Math.random()</h2><p><code>Math.random</code> 方法返回 <code>0</code> 到 <code>1</code> 之间的一个伪随机数，可能等于 <code>0</code> ，但一定小于 <code>1</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Math</span>.random() <span class="comment">// 0.38556088984648396</span></span><br></pre></td></tr></table></figure>

<hr>
<h1 id="Date-对象常见用法"><a href="#Date-对象常见用法" class="headerlink" title="Date 对象常见用法"></a>Date 对象常见用法</h1><p><code>Date</code> 对象是 JavaScript 原生的时间库。它以国际标准时间<code>（UTC）1970年1月1日00:00:00</code> 作为时间的零点，可以表示的时间范围是前后各1亿天（单位为毫秒）。</p>
<h2 id="Date"><a href="#Date" class="headerlink" title="Date()"></a>Date()</h2><p><code>Date</code> 对象可以作为普通函数直接调用，返回一个代表当前时间的字符串。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Date</span>() <span class="comment">// "Sat Dec 14 2019 14:43:17 GMT+0800 (中国标准时间)"</span></span><br></pre></td></tr></table></figure>

<p><code>Date</code> 可以当作构造函数使用，使用 <code>new</code> 命令，返回一个 <code>Date</code> 对象的实例。如果不加参数，实例代表的就是当前时间。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">new</span> <span class="built_in">Date</span>() <span class="comment">// Sat Dec 14 2019 14:43:42 GMT+0800 (中国标准时间)</span></span><br></pre></td></tr></table></figure>

<h2 id="Date-now"><a href="#Date-now" class="headerlink" title="Date.now()"></a>Date.now()</h2><p><code>Date.now</code> 方法返回当前时间距离时间零点（<code>1970年1月1日 00:00:00 UTC</code>）的毫秒数。时间戳的常用方法。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Date</span>.now() <span class="comment">// 1576306248004</span></span><br></pre></td></tr></table></figure>

<h2 id="get-类方法（set-）"><a href="#get-类方法（set-）" class="headerlink" title="get 类方法（set*）"></a>get 类方法（set*）</h2><p><code>Date</code> 对象提供了一系列 <code>get*</code> 方法，用于获取某个实例对象某方面的值。</p>
<p><code>set*</code> 类方法用于设置某个实例对象某方面的值，详情翻阅相关文档，用法差不多，这里做省略。</p>
<h3 id="getTime"><a href="#getTime" class="headerlink" title="getTime()"></a>getTime()</h3><p><code>getTime</code> 返回实例对象距离 <code>1970年1月1日 00:00:00</code> 的毫秒数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> time = <span class="keyword">new</span> <span class="built_in">Date</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment">// 时间戳常用写法</span></span><br><span class="line">time.getTime() <span class="comment">// 1576306856840</span></span><br></pre></td></tr></table></figure>

<h3 id="getFullYear-、getMonth-、getDate-、getDay"><a href="#getFullYear-、getMonth-、getDate-、getDay" class="headerlink" title="getFullYear()、getMonth()、getDate()、getDay()"></a>getFullYear()、getMonth()、getDate()、getDay()</h3><p><code>getFullYear</code> 返回四位数的年份。</p>
<p><code>getMonth</code> 返回月份（0 表示1月，11 表示 12月）。</p>
<p><code>getDate</code> 方法返回实例对象对应的每个月的几号（从 1 开始）。</p>
<p><code>getDay</code> 方法返回星期几，星期日为 0 ，星期一为 1 ，以此类推。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> time = <span class="keyword">new</span> <span class="built_in">Date</span>()</span><br><span class="line"></span><br><span class="line">time.getFullYear() <span class="comment">// 2019</span></span><br><span class="line">time.getMonth() <span class="comment">// 11</span></span><br><span class="line">time.getDate() <span class="comment">// 14</span></span><br><span class="line">time.getDay() <span class="comment">// 6</span></span><br></pre></td></tr></table></figure>

<h3 id="getHours-、getMinutes-、getSeconds"><a href="#getHours-、getMinutes-、getSeconds" class="headerlink" title="getHours()、getMinutes()、getSeconds()"></a>getHours()、getMinutes()、getSeconds()</h3><p><code>getHours</code> 返回小时（0 - 23）</p>
<p><code>getMinutes</code> 返回分钟</p>
<p><code>getSeconds</code> 返回秒</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> time = <span class="keyword">new</span> <span class="built_in">Date</span>()</span><br><span class="line"></span><br><span class="line">time.getHours() <span class="comment">// 15</span></span><br><span class="line">time.getMinutes() <span class="comment">// 17</span></span><br><span class="line">time.getSeconds() <span class="comment">// 45</span></span><br></pre></td></tr></table></figure>

<hr>
<h1 id="Regexp-用法"><a href="#Regexp-用法" class="headerlink" title="Regexp 用法"></a>Regexp 用法</h1><p>RegExp对象提供正则表达式的功能。</p>
<p>正则表达式是一种表达文本模式（即字符串结构）的方法，有点像字符串的模板，常常用来按照“给定模式”匹配文本。</p>
<h2 id="创建"><a href="#创建" class="headerlink" title="创建"></a>创建</h2><p>新建正则表达式有两种方法。</p>
<p>一种是使用字面量，以斜杠表示开始和结束。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> regex = <span class="regexp">/xyz/</span>;</span><br></pre></td></tr></table></figure>

<p>另一种是使用 <code>RegExp</code> 构造函数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> regex = <span class="keyword">new</span> <span class="built_in">RegExp</span>(<span class="string">'xyz'</span>);</span><br></pre></td></tr></table></figure>

<p>上面两种写法是等价的，都新建了一个内容为 <code>xyz</code> 的正则表达式对象。它们的主要区别是，第一种方法在引擎编译代码时，就会新建正则表达式，第二种方法在运行时新建正则表达式，所以前者的效率较高。而且，前者比较便利和直观，所以实际应用中，==基本上都采用字面量定义正则表达式。==</p>
<p><code>RegExp</code> 构造函数还可以接受第二个参数，表示修饰符。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">var regex &#x3D; new RegExp(&#39;xyz&#39;, &#39;i&#39;);</span><br><span class="line">&#x2F;&#x2F; 等价于</span><br><span class="line">var regex &#x3D; &#x2F;xyz&#x2F;i;</span><br></pre></td></tr></table></figure>

<h2 id="RegExp-prototype-test"><a href="#RegExp-prototype-test" class="headerlink" title="RegExp.prototype.test()"></a>RegExp.prototype.test()</h2><p>正则实例对象的 <code>test</code> 方法返回一个布尔值，表示当前模式是否能匹配参数字符串。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/cat/.test(<span class="string">'cats and dogs'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>上面代码验证参数字符串之中是否包含 <code>cat</code>，结果返回 <code>true</code>。</p>
<h2 id="RegExp-prototype-exec"><a href="#RegExp-prototype-exec" class="headerlink" title="RegExp.prototype.exec()"></a>RegExp.prototype.exec()</h2><p>正则实例对象的 <code>exec()</code> 方法，用来返回匹配结果。如果发现匹配，就返回一个数组，成员是匹配成功的子字符串，否则返回 <code>null</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> s = <span class="string">'_x_x'</span>;</span><br><span class="line"><span class="keyword">var</span> r1 = <span class="regexp">/x/</span>;</span><br><span class="line"><span class="keyword">var</span> r2 = <span class="regexp">/y/</span>;</span><br><span class="line"></span><br><span class="line">r1.exec(s) <span class="comment">// ["x"]</span></span><br><span class="line">r2.exec(s) <span class="comment">// null</span></span><br></pre></td></tr></table></figure>

<h2 id="字符串的实例方法"><a href="#字符串的实例方法" class="headerlink" title="字符串的实例方法"></a>字符串的实例方法</h2><p>字符串的实例方法之中，有4种与正则表达式有关。</p>
<ul>
<li><code>String.prototype.match()</code>：返回一个数组，成员是所有匹配的子字符串。</li>
<li><code>String.prototype.search()</code>：按照给定的正则表达式进行搜索，返回一个整数，表示匹配开始的位置。</li>
<li><code>String.prototype.replace()</code>：按照给定的正则表达式进行替换，返回替换后的字符串。</li>
<li><code>String.prototype.split()</code>：按照给定规则进行字符串分割，返回一个数组，包含分割后的各个成员。</li>
</ul>
<h3 id="String-prototype-match-1"><a href="#String-prototype-match-1" class="headerlink" title="String.prototype.match()"></a>String.prototype.match()</h3><p>字符串实例对象的match方法对字符串进行正则匹配，返回匹配结果。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> s = <span class="string">'_x_x'</span>;</span><br><span class="line"><span class="keyword">var</span> r1 = <span class="regexp">/x/</span>;</span><br><span class="line"><span class="keyword">var</span> r2 = <span class="regexp">/y/</span>;</span><br><span class="line"></span><br><span class="line">s.match(r1) <span class="comment">// ["x"]</span></span><br><span class="line">s.match(r2) <span class="comment">// null</span></span><br></pre></td></tr></table></figure>

<h3 id="String-prototype-search"><a href="#String-prototype-search" class="headerlink" title="String.prototype.search()"></a>String.prototype.search()</h3><p>字符串对象的 <code>search</code> 方法，返回第一个满足条件的匹配结果在整个字符串中的位置。如果没有任何匹配，则返回 <code>-1</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'_x_x'</span>.search(<span class="regexp">/x/</span>)</span><br><span class="line"><span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<h3 id="String-prototype-replace-1"><a href="#String-prototype-replace-1" class="headerlink" title="String.prototype.replace()"></a>String.prototype.replace()</h3><p>字符串对象的 <code>replace</code> 方法可以替换匹配的值。它接受两个参数，第一个是正则表达式，表示搜索模式，第二个是替换的内容。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">str.replace(search, replacement)</span><br></pre></td></tr></table></figure>

<p>正则表达式如果不加g修饰符，就替换第一个匹配成功的值，否则替换所有匹配成功的值。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'aaa'</span>.replace(<span class="string">'a'</span>, <span class="string">'b'</span>) <span class="comment">// "baa"</span></span><br><span class="line"><span class="string">'aaa'</span>.replace(<span class="regexp">/a/</span>, <span class="string">'b'</span>) <span class="comment">// "baa"</span></span><br><span class="line"><span class="string">'aaa'</span>.replace(<span class="regexp">/a/g</span>, <span class="string">'b'</span>) <span class="comment">// "bbb"</span></span><br></pre></td></tr></table></figure>

<h3 id="String-prototype-split-1"><a href="#String-prototype-split-1" class="headerlink" title="String.prototype.split()"></a>String.prototype.split()</h3><p>字符串对象的 <code>split</code> 方法按照正则规则分割字符串，返回一个由分割后的各个部分组成的数组。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">str.split(separator, [limit])</span><br></pre></td></tr></table></figure>

<p>该方法接受两个参数，第一个参数是正则表达式，表示分隔规则，第二个参数是返回数组的最大成员数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 非正则分隔</span></span><br><span class="line"><span class="string">'a,  b,c, d'</span>.split(<span class="string">','</span>)</span><br><span class="line"><span class="comment">// [ 'a', '  b', 'c', ' d' ]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 正则分隔，去除多余的空格</span></span><br><span class="line"><span class="string">'a,  b,c, d'</span>.split(<span class="regexp">/, */</span>)</span><br><span class="line"><span class="comment">// [ 'a', 'b', 'c', 'd' ]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 指定返回数组的最大成员</span></span><br><span class="line"><span class="string">'a,  b,c, d'</span>.split(<span class="regexp">/, */</span>, <span class="number">2</span>)</span><br><span class="line">[ <span class="string">'a'</span>, <span class="string">'b'</span> ]</span><br></pre></td></tr></table></figure>

<h2 id="匹配规则"><a href="#匹配规则" class="headerlink" title="匹配规则"></a>匹配规则</h2><h3 id="字面量字符和元字符"><a href="#字面量字符和元字符" class="headerlink" title="字面量字符和元字符"></a>字面量字符和元字符</h3><p>大部分字符在正则表达式中，就是字面的含义，比如 <code>/a/</code> 匹配 <code>a</code>，<code>/b/</code> 匹配 <code>b</code>。如果在正则表达式之中，某个字符只表示它字面的含义（就像前面的 <code>a</code> 和 <code>b</code>），那么它们就叫做“字面量字符”。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/dog/.test(<span class="string">'old dog'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>除了字面量字符以外，还有一部分字符有特殊含义，不代表字面的意思。它们叫做“元字符”，主要有以下几个。</p>
<h4 id="点字符（-）"><a href="#点字符（-）" class="headerlink" title="点字符（.）"></a>点字符（.）</h4><p>点字符（<code>.</code>）匹配除回车（<code>\r</code>）、换行(<code>\n</code>) 、行分隔符（<code>\u2028</code>）和段分隔符（<code>\u2029</code>）以外的所有字符。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/c.t/</span><br></pre></td></tr></table></figure>

<p>上面代码中，<code>c.t</code> 匹配 <code>c</code> 和 <code>t</code> 之间包含任意一个字符的情况，只要这三个字符在同一行，比如 <code>cat、c2t、c-t</code> 等等，但是不匹配 <code>coot</code>。</p>
<h4 id="位置字符"><a href="#位置字符" class="headerlink" title="位置字符"></a>位置字符</h4><p>位置字符用来提示字符所处的位置，主要有两个字符。</p>
<ul>
<li><code>^</code> 表示字符串的开始位置</li>
<li><code>$</code> 表示字符串的结束位置</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#x2F;&#x2F; test必须出现在开始位置</span><br><span class="line">&#x2F;^test&#x2F;.test(&#39;test123&#39;) &#x2F;&#x2F; true</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; test必须出现在结束位置</span><br><span class="line">&#x2F;test$&#x2F;.test(&#39;new test&#39;) &#x2F;&#x2F; true</span><br><span class="line"></span><br><span class="line">&#x2F;&#x2F; 从开始位置到结束位置只有test</span><br><span class="line">&#x2F;^test$&#x2F;.test(&#39;test&#39;) &#x2F;&#x2F; true</span><br><span class="line">&#x2F;^test$&#x2F;.test(&#39;test test&#39;) &#x2F;&#x2F; false</span><br></pre></td></tr></table></figure>

<h4 id="选择符（-）"><a href="#选择符（-）" class="headerlink" title="选择符（|）"></a>选择符（|）</h4><p>竖线符号（<code>|</code>）在正则表达式中表示“或关系”，即 <code>cat|dog</code> 表示匹配 <code>cat</code> 或 <code>dog</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/<span class="number">11</span>|<span class="number">22</span>/.test(<span class="string">'911'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，正则表达式指定必须匹配 <code>11</code> 或 <code>22</code>。</p>
<p>多个选择符可以联合使用。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 匹配fred、barney、betty之中的一个</span></span><br><span class="line">/fred|barney|betty/</span><br></pre></td></tr></table></figure>

<p>选择符会包括它前后的多个字符，比如 <code>/ab|cd/</code> 指的是匹配 <code>ab</code> 或者 <code>cd</code> ，而不是指匹配 <code>b</code> 或者 <code>c</code>。如果想修改这个行为，可以使用圆括号。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/a( |\t)b/.test(<span class="string">'a\tb'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h3 id="转义符"><a href="#转义符" class="headerlink" title="转义符"></a>转义符</h3><p>正则表达式中那些有特殊含义的元字符，如果要匹配它们本身，就需要在它们前面要加上反斜杠。比如要匹配 <code>+</code>，就要写成 <code>\+</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">/<span class="number">1</span>+<span class="number">1</span>/.test(<span class="string">'1+1'</span>)</span><br><span class="line"><span class="comment">// false</span></span><br><span class="line"></span><br><span class="line">/<span class="number">1</span>\+<span class="number">1</span>/.test(<span class="string">'1+1'</span>)</span><br><span class="line"><span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>正则表达式中，需要反斜杠转义的，一共有12个字符：<code>^、.、[、$、(、)、|、*、+、?、{</code> 和 <code>\</code>。需要特别注意的是，如果使用 <code>RegExp</code> 方法生成正则对象，转义需要使用两个斜杠，因为字符串内部会先转义一次。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">(<span class="keyword">new</span> <span class="built_in">RegExp</span>(<span class="string">'1\+1'</span>)).test(<span class="string">'1+1'</span>)</span><br><span class="line"><span class="comment">// false</span></span><br><span class="line"></span><br><span class="line">(<span class="keyword">new</span> <span class="built_in">RegExp</span>(<span class="string">'1\\+1'</span>)).test(<span class="string">'1+1'</span>)</span><br><span class="line"><span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h3 id="特殊字符"><a href="#特殊字符" class="headerlink" title="特殊字符"></a>特殊字符</h3><p>正则表达式对一些不能打印的特殊字符，提供了表达方法。</p>
<ul>
<li><code>\cX</code> 表示 <code>Ctrl-[X]</code>，其中的 <code>X</code> 是 <code>A-Z</code> 之中任一个英文字母，用来匹配控制字符。</li>
<li><code>[\b]</code> 匹配退格键(<code>U+0008</code>)，不要与 <code>\b</code> 混淆。</li>
<li><code>\n</code> 匹配换行键。</li>
<li><code>\r</code> 匹配回车键。</li>
<li><code>\t</code> 匹配制表符 <code>tab</code>（<code>U+0009</code>）。</li>
<li><code>\v</code> 匹配垂直制表符（<code>U+000B</code>）。</li>
<li><code>\f</code> 匹配换页符（<code>U+000C</code>）。</li>
<li><code>\0</code> 匹配null字符（<code>U+0000</code>）。</li>
<li><code>\xhh</code> 匹配一个以两位十六进制数（<code>\x00-\xFF</code>）表示的字符。</li>
<li><code>\uhhhh</code> 匹配一个以四位十六进制数（<code>\u0000-\uFFFF</code>）表示的 <code>Unicode</code> 字符。</li>
</ul>
<h3 id="字符类"><a href="#字符类" class="headerlink" title="字符类"></a>字符类</h3><p>字符类表示有一系列字符可供选择，只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内，比如 <code>[xyz]</code>  表示 <code>x、y、z</code> 之中任选一个匹配。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/[abc]/.test(<span class="string">'hello world'</span>) <span class="comment">// false</span></span><br><span class="line">/[abc]/.test(<span class="string">'apple'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，字符串 <code>hello world</code> 不包含 <code>a、b、c</code> 这三个字母中的任一个，所以返回 <code>false</code>；字符串 <code>apple</code> 包含字母 <code>a</code>，所以返回 <code>true</code>。</p>
<p>有两个字符在字符类中有特殊含义。</p>
<h4 id="脱字符（-）"><a href="#脱字符（-）" class="headerlink" title="脱字符（^）"></a>脱字符（<code>^</code>）</h4><p>如果方括号内的第一个字符是 <code>[^]</code>，则表示除了字符类之中的字符，其他字符都可以匹配。比如，<code>[^xyz]</code> 表示除了 <code>x、y、z</code> 之外都可以匹配。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/[^abc]/.test(<span class="string">'bbc news'</span>) <span class="comment">// true</span></span><br><span class="line">/[^abc]/.test(<span class="string">'bbc'</span>) <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，字符串 <code>bbc news</code> 包含 <code>a、b、c</code> 以外的其他字符，所以返回 <code>true</code>；字符串 <code>bbc</code> 不包含 <code>a、b、c</code> 以外的其他字符，所以返回 <code>false</code>。</p>
<h4 id="连字符（-）"><a href="#连字符（-）" class="headerlink" title="连字符（-）"></a>连字符（<code>-</code>）</h4><p>某些情况下，对于连续序列的字符，连字符（<code>-</code>）用来提供简写形式，表示字符的连续范围。比如，<code>[abc]</code> 可以写成 <code>[a-c]</code>，<code>[0123456789]</code> 可以写成 <code>[0-9]</code>，同理 <code>[A-Z]</code> 表示 <code>26</code> 个大写字母。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/a-z/.test(<span class="string">'b'</span>) <span class="comment">// false</span></span><br><span class="line">/[a-z]/.test(<span class="string">'b'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，当连字号（<code>dash</code>）不出现在方括号之中，就不具备简写的作用，只代表字面的含义，所以不匹配字符b。只有当连字号用在方括号之中，才表示连续的字符序列。</p>
<p>以下都是合法的字符类简写形式。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">0</span><span class="number">-9.</span>,]</span><br><span class="line">[<span class="number">0</span><span class="number">-9</span>a-fA-F]</span><br><span class="line">[a-zA-Z0<span class="number">-9</span>-]</span><br><span class="line">[<span class="number">1</span><span class="number">-31</span>]</span><br></pre></td></tr></table></figure>

<p>上面代码中最后一个字符类 <code>[1-31]</code>，不代表 <code>1</code> 到 <code>31</code>，只代表 <code>1</code> 到 <code>3</code>。</p>
<h3 id="预定义模式"><a href="#预定义模式" class="headerlink" title="预定义模式"></a>预定义模式</h3><p>预定义模式指的是某些常见模式的简写方式。</p>
<ul>
<li><code>\d</code> 匹配 <code>0-9</code> 之间的任一数字，相当于 <code>[0-9]</code>。</li>
<li><code>\D</code> 匹配所有 <code>0-9</code> 以外的字符，相当于 <code>[^0-9]</code>。</li>
<li><code>\w</code> 匹配任意的字母、数字和下划线，相当于 <code>[A-Za-z0-9_]</code>。</li>
<li><code>\W</code> 除所有字母、数字和下划线以外的字符，相当于 <code>[^A-Za-z0-9_]</code>。</li>
<li><code>\s</code> 匹配空格（包括换行符、制表符、空格符等），相等于 <code>[ \t\r\n\v\f]</code>。</li>
<li><code>\S</code> 匹配非空格的字符，相当于 <code>[^ \t\r\n\v\f]</code>。</li>
<li><code>\b</code> 匹配词的边界。</li>
<li><code>\B</code> 匹配非词边界，即在词的内部。</li>
</ul>
<h3 id="重复类"><a href="#重复类" class="headerlink" title="重复类"></a>重复类</h3><p>模式的精确匹配次数，使用大括号（<code>{}</code>）表示。<code>{n}</code> 表示恰好重复 <code>n</code> 次，<code>{n,}</code>表示至少重复 <code>n</code> 次，<code>{n,m}</code> 表示重复不少于 <code>n</code> 次，不多于 <code>m</code> 次。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/lo&#123;<span class="number">2</span>&#125;k/.test(<span class="string">'look'</span>) <span class="comment">// true</span></span><br><span class="line">/lo&#123;<span class="number">2</span>,<span class="number">5</span>&#125;k/.test(<span class="string">'looook'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，第一个模式指定 <code>o</code> 连续出现 <code>2</code> 次，第二个模式指定 <code>o</code> 连续出现 <code>2</code> 次到 <code>5</code> 次之间。</p>
<h3 id="量词符"><a href="#量词符" class="headerlink" title="量词符"></a>量词符</h3><p>量词符用来设定某个模式出现的次数。</p>
<ul>
<li><code>?</code> 问号表示某个模式出现 <code>0</code> 次或 <code>1</code> 次，等同于 <code>{0, 1}</code>。</li>
<li><code>*</code> 星号表示某个模式出现 <code>0</code> 次或多次，等同于 <code>{0,}</code>。</li>
<li><code>+</code> 加号表示某个模式出现 <code>1</code> 次或多次，等同于 <code>{1,}</code>。</li>
</ul>
<h3 id="贪婪模式"><a href="#贪婪模式" class="headerlink" title="贪婪模式"></a>贪婪模式</h3><p>之前的的三个量词符，默认情况下都是最大可能匹配，即匹配到下一个字符不满足匹配规则为止。这被称为贪婪模式。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> s = <span class="string">'aaa'</span>;</span><br><span class="line">s.match(<span class="regexp">/a+/</span>) <span class="comment">// ["aaa"]</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，模式是 <code>/a+/</code>，表示匹配 <code>1</code> 个 <code>a</code> 或多个 <code>a</code>，那么到底会匹配几个 <code>a</code> 呢？因为默认是贪婪模式，会一直匹配到字符 <code>a</code> 不出现为止，所以匹配结果是 <code>3</code> 个 <code>a</code>。</p>
<p>除了贪婪模式，还有非贪婪模式的加号（<code>+?</code>），非贪婪模式的星号（<code>*?</code>）和非贪婪模式的问号（<code>??</code>）。</p>
<ul>
<li><code>+?</code>：表示某个模式出现 <code>1</code> 次或多次，匹配时采用非贪婪模式。</li>
<li><code>*?</code>：表示某个模式出现 <code>0</code> 次或多次，匹配时采用非贪婪模式。</li>
<li><code>??</code>：表格某个模式出现 <code>0</code> 次或 <code>1</code> 次，匹配时采用非贪婪模式。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">'abb'</span>.match(<span class="regexp">/ab*/</span>) <span class="comment">// ["abb"]</span></span><br><span class="line"><span class="string">'abb'</span>.match(<span class="regexp">/ab*?/</span>) <span class="comment">// ["a"]</span></span><br><span class="line"></span><br><span class="line"><span class="string">'abb'</span>.match(<span class="regexp">/ab?/</span>) <span class="comment">// ["ab"]</span></span><br><span class="line"><span class="string">'abb'</span>.match(<span class="regexp">/ab??/</span>) <span class="comment">// ["a"]</span></span><br></pre></td></tr></table></figure>

<p>上面例子中，<code>/ab*/</code> 表示如果 <code>a</code> 后面有多个 <code>b</code>，那么匹配尽可能多的 <code>b</code>；<code>/ab*?/</code> 表示匹配尽可能少的 <code>b</code>，也就是 <code>0</code> 个 <code>b</code>。</p>
<h3 id="修饰符"><a href="#修饰符" class="headerlink" title="修饰符"></a>修饰符</h3><p>修饰符表示模式的附加规则，放在正则模式的最尾部。</p>
<p>修饰符可以单个使用，也可以多个一起使用。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 单个修饰符</span></span><br><span class="line"><span class="keyword">var</span> regex = <span class="regexp">/test/i</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 多个修饰符</span></span><br><span class="line"><span class="keyword">var</span> regex = <span class="regexp">/test/ig</span>;</span><br></pre></td></tr></table></figure>

<h4 id="g-修饰符"><a href="#g-修饰符" class="headerlink" title="g 修饰符"></a>g 修饰符</h4><p>默认情况下，第一次匹配成功后，正则对象就停止向下匹配了。<code>g</code> 修饰符表示全局匹配（global），加上它以后，正则对象将匹配全部符合条件的结果，主要用于搜索和替换。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> regex = <span class="regexp">/b/</span>;</span><br><span class="line"><span class="keyword">var</span> str = <span class="string">'abba'</span>;</span><br><span class="line"></span><br><span class="line">regex.test(str); <span class="comment">// true</span></span><br><span class="line">regex.test(str); <span class="comment">// true</span></span><br><span class="line">regex.test(str); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，正则模式不含 <code>g</code> 修饰符，每次都是从字符串头部开始匹配。所以，连续做了三次匹配，都返回 <code>true</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> regex = <span class="regexp">/b/g</span>;</span><br><span class="line"><span class="keyword">var</span> str = <span class="string">'abba'</span>;</span><br><span class="line"></span><br><span class="line">regex.test(str); <span class="comment">// true</span></span><br><span class="line">regex.test(str); <span class="comment">// true</span></span><br><span class="line">regex.test(str); <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，正则模式含有 <code>g</code> 修饰符，每次都是从上一次匹配成功处，开始向后匹配。因为字符串 <code>abba</code> 只有两个 <code>b</code>，所以前两次匹配结果为 <code>true</code>，第三次匹配结果为 <code>false</code>。</p>
<h4 id="i-修饰符"><a href="#i-修饰符" class="headerlink" title="i 修饰符"></a>i 修饰符</h4><p>默认情况下，正则对象区分字母的大小写，加上 <code>i</code> 修饰符以后表示忽略大小写（ignoreCase）。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/abc/.test(<span class="string">'ABC'</span>) <span class="comment">// false</span></span><br><span class="line">/abc/i.test(<span class="string">'ABC'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h4 id="m-修饰符"><a href="#m-修饰符" class="headerlink" title="m 修饰符"></a>m 修饰符</h4><p><code>m</code> 修饰符表示多行模式，会修改 <code>^</code> 和 <code>$</code> 的行为。默认情况下（即不加 <code>m</code> 修饰符时），<code>^</code> 和 <code>$</code> 匹配字符串的开始处和结尾处，加上 <code>m</code> 修饰符以后，<code>^</code> 和 <code>$</code> 还会匹配行首和行尾，即 <code>^</code> 和 <code>$</code> 会识别换行符（<code>\n</code>）。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">/world$/.test(<span class="string">'hello world\n'</span>) <span class="comment">// false</span></span><br><span class="line">/world$/m.test(<span class="string">'hello world\n'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<hr>
<h1 id="JSON-对象用法"><a href="#JSON-对象用法" class="headerlink" title="JSON 对象用法"></a>JSON 对象用法</h1><p><code>JSON</code> 格式是一种用于数据交换的文本格式。</p>
<p>每个 <code>JSON</code> 对象就是一个值，可能是一个数组或对象，也可能是一个原始类型的值。</p>
<p><code>JSON</code> 对值的类型和格式有严格的规定：</p>
<ul>
<li>复合类型的值只能是数组或对象，不能是函数、正则表达式对象、日期对象。</li>
<li>原始类型的值只有四种：字符串、数值（必须以十进制表示）、布尔值和 <code>null</code>（不能使用 <code>NaN</code>, <code>Infinity</code>, <code>-Infinity</code> 和 <code>undefined</code>）。</li>
<li>==字符串必须使用双引号表示，不能使用单引号。==</li>
<li>对象的键名必须放在双引号里面。</li>
<li>数组或对象最后一个成员的后面，不能加逗号。</li>
</ul>
<h2 id="JSON-stringify-、JSON-parse"><a href="#JSON-stringify-、JSON-parse" class="headerlink" title="JSON.stringify()、JSON.parse()"></a>JSON.stringify()、JSON.parse()</h2><p><code>JSON.stringify</code> 方法用于将一个值转为 <code>JSON</code> 字符串。该字符串符合 <code>JSON</code> 格式，并且可以被 <code>JSON.parse</code> 方法还原。</p>
<p><code>JSON.parse</code> 方法用于将 <code>JSON</code> 字符串转换成对应的值。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj =&#123;<span class="attr">a</span>:<span class="number">123</span>,<span class="attr">b</span>:<span class="string">'BBB'</span>&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">JSON</span>.stringify(obj) <span class="comment">// "&#123;"a":123,"b":"BBB"&#125;"</span></span><br></pre></td></tr></table></figure>

<hr>
<h1 id="面向对象编程"><a href="#面向对象编程" class="headerlink" title="面向对象编程"></a>面向对象编程</h1><p>面向对象编程（Object Oriented Programming，缩写为 OOP）是目前主流的编程范式。它将真实世界各种复杂的关系，抽象为一个个对象，然后由对象之间的分工与合作，完成对真实世界的模拟。</p>
<h2 id="构造函数"><a href="#构造函数" class="headerlink" title="构造函数"></a>构造函数</h2><p>JavaScript 语言使用构造函数（<code>constructor</code>）作为对象的模板。所谓“构造函数”，就是专门用来生成实例对象的函数。</p>
<p>构造函数就是一个普通的函数，为了与普通函数区别，构造函数名字的第一个字母通常大写。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> Vehicle = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">this</span>.price = <span class="number">1000</span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>构造函数特点：</p>
<ul>
<li>函数体内部使用了 <code>this</code> 关键字，代表了所要生成对象的实例。</li>
<li>生成对象时，必须使用 <code>new</code> 命令。</li>
</ul>
<h2 id="new-命令"><a href="#new-命令" class="headerlink" title="new 命令"></a>new 命令</h2><p><code>new</code> 命令的作用，就是执行构造函数，返回一个实例对象。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> Vehicle = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">this</span>.price = <span class="number">1000</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> v = <span class="keyword">new</span> Vehicle();</span><br><span class="line">v.price <span class="comment">// 1000</span></span><br></pre></td></tr></table></figure>

<p><code>new</code> 命令原理：</p>
<ul>
<li>==创建一个空对象，作为要返回的对象实例。==</li>
<li>==将这个空对象的原型，指向构造函数的 <code>prototype</code> 属性。==</li>
<li>==将这个空对象赋值给函数内部的 <code>this</code> 关键字。==</li>
<li>==开始执行构造函数内部代码。==</li>
</ul>
<h2 id="Object-create-创建实例对象"><a href="#Object-create-创建实例对象" class="headerlink" title="Object.create() 创建实例对象"></a>Object.create() 创建实例对象</h2><p>构造函数作为模板，可以生成实例对象。但是，有时候需要用对象作为模板，生成新的实例对象，这时就可以使用 <code>Object.create()</code> 方法。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> guopengsong = &#123;</span><br><span class="line">    mingzi:<span class="string">'郭鹏松'</span>,</span><br><span class="line">    xingbie:<span class="string">'男'</span>,</span><br><span class="line">    leixing:<span class="string">'人类'</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> pingyuan = <span class="built_in">Object</span>.create(guopengsong)</span><br><span class="line"></span><br><span class="line">pingyuan.leixing <span class="comment">// 人类</span></span><br><span class="line">pingyuan.xingbie <span class="comment">// 男</span></span><br></pre></td></tr></table></figure>

<p>关于 <code>Object.create()</code> 详细用法，后面相关章节有，这里仅仅作为构造函数创建实例对象的补充。</p>
<h2 id="this-关键字"><a href="#this-关键字" class="headerlink" title="this 关键字"></a>this 关键字</h2><p><code>this</code> 就是属性或方法“当前”所在的对象。不管是什么场合，<code>this</code> 都有一个共同点：==它总是返回一个对象。==</p>
<p>==在 JavaScript 语言中，一切皆对象，运行环境也是对象，所以函数都是在某个对象之中运行，<code>this</code> 就是函数运行时所在的对象（环境）。== 这本来不会让用户糊涂，但是 JavaScript 支持运行环境动态切换，也就是说，<code>this</code> 的指向时动态的，没办法事先确定到底指向哪个对象，这才是让人困惑的地方。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="string">'姓名：'</span>+ <span class="keyword">this</span>.name;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> A = &#123;</span><br><span class="line">  name: <span class="string">'张三'</span>,</span><br><span class="line">  describe: f</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> B = &#123;</span><br><span class="line">  name: <span class="string">'李四'</span>,</span><br><span class="line">  describe: f</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">A.describe() <span class="comment">// "姓名：张三"</span></span><br><span class="line">B.describe() <span class="comment">// "姓名：李四"</span></span><br></pre></td></tr></table></figure>

<p><code>this</code> 使用场合：</p>
<ul>
<li>==全局环境：全局环境使用 <code>this</code> ，它指向的就是顶层对象 <code>window</code>。==</li>
<li>==构造函数：构造函数中的 <code>this</code> ，指的就是实例对象。==</li>
<li>==对象的方法：如果对象的方法里面包含 <code>this</code> , <code>this</code> 的指向就是方法所运行时所在的对象。该方法赋值给另一个对象，就会改变 this 的指向。==</li>
</ul>
<p><code>this</code> 使用注意点：</p>
<ul>
<li>避免多层 <code>this</code>：由于 <code>this</code> 的指向是不确定的，避免在函数中包含多层 <code>this</code>。</li>
<li>避免数组方法中 <code>this</code>：数组的 <code>map</code> 和 <code>foreach</code> 方法，允许提供一个函数作为参数。这个函数内部不应该使用 <code>this</code>。</li>
<li>避免回调函数中的 <code>this</code>：回调函数中的 <code>this</code> 往往会改变指向，最好避免使用。</li>
</ul>
<h3 id="绑定-this-的方法"><a href="#绑定-this-的方法" class="headerlink" title="绑定 this 的方法"></a>绑定 this 的方法</h3><p>==JavaScript 提供了 <code>call、apply、bind</code> 这三个方法，来切换/固定 <code>this</code> 的指向。==</p>
<h4 id="Function-prototype-call"><a href="#Function-prototype-call" class="headerlink" title="Function.prototype.call()"></a>Function.prototype.call()</h4><p>==函数实例的 <code>call</code> 方法，可以指定函数内部的 <code>this</code>  指向（即函数执行时所在的作用域），然后在指定的作用域中，调用该函数。==</p>
<p><code>call</code> 方法的参数，应该是一个对象。如果参数为 <code>空、null</code> 和 <code>undefined</code> ，则默认传入全局对象。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> f = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">f() === <span class="built_in">window</span> <span class="comment">// true</span></span><br><span class="line">f.call(obj) === obj <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>==<code>call</code> 方法还可以接受多个参数。<code>call</code> 的第一个参数就是 <code>this</code> 所要指向的那个对象，后面的参数则是函数调用时所需的参数。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">func.call(thisValue, arg1, arg2, ...)</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">a, b</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">return</span> a + b;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">add.call(<span class="keyword">this</span>, <span class="number">1</span>, <span class="number">2</span>) <span class="comment">// 3</span></span><br></pre></td></tr></table></figure>

<h4 id="Function-prototype-apply"><a href="#Function-prototype-apply" class="headerlink" title="Function.prototype.apply()"></a>Function.prototype.apply()</h4><p><code>apply</code> 方法的作用与 <code>call</code> 方法类似，也是改变 <code>this</code> 指向，然后再调用该函数。==唯一的区别就是，它接收一个数组作为函数执行时的参数。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">func.apply(thisValue, [arg1, arg2, ...])</span><br></pre></td></tr></table></figure>

<h4 id="Function-prototype-bind"><a href="#Function-prototype-bind" class="headerlink" title="Function.prototype.bind()"></a>Function.prototype.bind()</h4><p><code>bind</code> 方法用于将函数体内的 <code>this</code> 绑定到某个对象，然后返回一个新函数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> d = <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br><span class="line">d.getTime() <span class="comment">// 1481869925657</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> print = d.getTime;</span><br><span class="line">print() <span class="comment">// Uncaught TypeError: this is not a Date object.</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，我们将 <code>d.getTime()</code> 方法赋给变量 <code>print</code>，然后调用 <code>print()</code> 就报错了。这是因为 <code>getTime()</code> 方法内部的 <code>this</code>，绑定 <code>Date</code> 对象的实例，赋给变量 <code>print</code> 以后，内部的 <code>this</code> 已经不指向 <code>Date</code> 对象的实例了。</p>
<p><code>bind()</code> 方法可以解决这个问题。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> print = d.getTime.bind(d);</span><br><span class="line">print() <span class="comment">// 1481869925657</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，<code>bind()</code> 方法将 <code>getTime()</code> 方法内部的 <code>this</code> 绑定到 <code>d</code> 对象，这时就可以安全地将这个方法赋值给其他变量了。</p>
<p>==<code>bind()</code> 的作用与 <code>call()</code> 和 <code>apply()</code> 一样，都是可以改变函数运行时上下文，区别是 <code>call()</code> 和 <code>apply()</code> 在调用函数之后会立即执行，而 <code>bind()</code> 方法调用并改变函数运行时上下文后，返回一个新的函数，供我们需要时再调用。==</p>
<h3 id="如何选用"><a href="#如何选用" class="headerlink" title="如何选用"></a>如何选用</h3><ul>
<li>如果不需要关心具体有多少参数被传入函数，选用 <code>apply()</code>；</li>
<li>如果确定函数可接收多少个参数，并且想一目了然表达形参和实参的对应关系，用 <code>call()</code>；</li>
<li>如果想要将来再调用方法，不需立即得到函数返回结果，则使用 <code>bind()</code>。</li>
</ul>
<h3 id="特点总结"><a href="#特点总结" class="headerlink" title="特点总结"></a>特点总结</h3><ul>
<li><code>call()</code>、<code>apply()</code> 和 <code>bind()</code> 都是用来改变函数执行时的上下文，可借助它们实现继承；</li>
<li><code>call()</code> 和 <code>apply()</code> 唯一区别是参数不一样，<code>call()</code> 是 <code>apply()</code> 的语法糖；</li>
<li><code>bind()</code> 是返回一个新函数，供以后调用，而 <code>apply()</code> 和 <code>call()</code> 是立即调用。</li>
</ul>
<h2 id="对象的继承"><a href="#对象的继承" class="headerlink" title="对象的继承"></a>对象的继承</h2><p>面向对象编程很重要的一个方面，就是对象的继承。A 对象通过继承 B 对象，就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。</p>
<p>大部分面向对象的编程语言，都是通过“类”（<code>class</code>）实现对象的继承。传统上，JavaScript 语言的继承不通过 <code>class</code>，而是通过“原型对象”（<code>prototype</code>）实现。</p>
<h3 id="原型对象概述"><a href="#原型对象概述" class="headerlink" title="原型对象概述"></a>原型对象概述</h3><h4 id="构造函数的缺点"><a href="#构造函数的缺点" class="headerlink" title="构造函数的缺点"></a>构造函数的缺点</h4><p>通过构造函数为实例对象定义属性，虽然方便，但是又个缺点，==同一个构造函数的多个实例对象之间，无法共享属性，从而对系统资源造成浪费。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Cat</span>(<span class="params">name,color</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.name = name;</span><br><span class="line">    <span class="keyword">this</span>.color = color;</span><br><span class="line">    <span class="keyword">this</span>.meow = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'喵喵'</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> cat1 = <span class="keyword">new</span> Cat(<span class="string">'大毛'</span>,<span class="string">'白色'</span>)；</span><br><span class="line"><span class="keyword">var</span> cat2 = <span class="keyword">new</span> Cat(<span class="string">'二毛'</span>,<span class="string">'黄色'</span>);</span><br><span class="line"></span><br><span class="line">cat1.meow === cat2.meow <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<h4 id="prototype-属性的作用"><a href="#prototype-属性的作用" class="headerlink" title="prototype 属性的作用"></a>prototype 属性的作用</h4><p>JavaScript 规定，==每个函数都有一个 <code>prototype</code> 属性，指向一个对象。原型对象的所有属性和方法，都能被实例对象共享。如果属性和方法定义在原型上，那么所有实例就能共享。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">f</span>(<span class="params"></span>) </span>&#123; &#125;</span><br><span class="line"><span class="keyword">typeof</span> f.prototype <span class="comment">// 'object'</span></span><br></pre></td></tr></table></figure>

<p>对于普通函数来说，该属性基本无用。==对于构造函数来说，生成实例的时候，该属性（<code>prototype</code>）会自动成为实例对象的原型。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Animal</span>(<span class="params">name</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">this</span>.name = name;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Animal.prototype.color = <span class="string">'white'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> cat1 = <span class="keyword">new</span> Animal(<span class="string">'大毛'</span>);</span><br><span class="line"><span class="keyword">var</span> cat2 = <span class="keyword">new</span> Animal(<span class="string">'二毛'</span>);</span><br><span class="line"></span><br><span class="line">cat1.color <span class="comment">// 'white'</span></span><br><span class="line">cat2.color <span class="comment">// 'white'</span></span><br></pre></td></tr></table></figure>

<p>==原型对象的属性不是实例对象自身的属性。只要修改原型对象，变动就会立刻体现在所有实例对象上。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Animal.prototype.color = <span class="string">'yellow'</span>;</span><br><span class="line"></span><br><span class="line">cat1.color <span class="comment">// "yellow"</span></span><br><span class="line">cat2.color <span class="comment">// "yellow"</span></span><br></pre></td></tr></table></figure>

<p>==如果实例对象自身就有某个属性或者方法，它就不会再去原型对象寻找这个属性或者方法。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">cat1.color = <span class="string">'black'</span>;</span><br><span class="line"></span><br><span class="line">cat1.color <span class="comment">// 'black'</span></span><br><span class="line">cat2.color <span class="comment">// 'yellow'</span></span><br><span class="line">Animal.prototype.color <span class="comment">// 'yellow';</span></span><br></pre></td></tr></table></figure>

<p>==原型对象的作用，就是定义所有实例对象共享的属性和方法。==</p>
<p><img src="https://inews.gtimg.com/newsapp_ls/0/12133946205/0" alt="原型示意图"></p>
<h4 id="原型链"><a href="#原型链" class="headerlink" title="原型链"></a>原型链</h4><p>==JavaScript 规定，所有的对象都有自己的原型对象（<code>prototype</code>）。一方面，任何一个对象，都可以充当其它对象的原型；另一方面，由于原型对象也是对象，所以它也有自己的原型。因此，就会形成一个“原型链”：对象到原型，再到原型的原型……==</p>
<p>==一层一层往上追溯，所有的对象原型最终都可以追溯到 <code>Object.prototype</code> ，即 <code>Object</code> 构造函数的 <code>prototype</code> 属性。<code>Object.prototype</code> 的原型是 <code>null</code>。<code>null</code> 没有任何属性和方法，也没有自己的原型。因此，原型链的尽头就是 <code>null</code>。==</p>
<h4 id="constructor-属性"><a href="#constructor-属性" class="headerlink" title="constructor 属性"></a>constructor 属性</h4><p>==<code>prototype</code> 对象有一个 <code>constructor</code> 属性，默认指向 <code>prototype</code> 对象所在的构造函数。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">P</span>(<span class="params"></span>)</span>&#123; &#125;;</span><br><span class="line"></span><br><span class="line">P.prototype.constructor === P <span class="comment">// ture</span></span><br></pre></td></tr></table></figure>

<p><img src="https://inews.gtimg.com/newsapp_ls/0/12133956641/0" alt="原型链示意图"></p>
<p>==<code>constructor</code> 属性表示原型对象与构造函数之间的关联关系，如果修改了原型对象，一般会同时修改 <code>constructor</code> 属性，防止引用的时候出错。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 坏的写法</span></span><br><span class="line">C.prototype = &#123;</span><br><span class="line">    method1:<span class="function"><span class="keyword">function</span>(<span class="params">...</span>)</span>&#123;...&#125;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 好的写法</span></span><br><span class="line">C.prototype = &#123;</span><br><span class="line">    <span class="keyword">constructor</span>:C,</span><br><span class="line">    method1:function(...)&#123;...&#125;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 更好的写法</span></span><br><span class="line">C.prototype.method1 = <span class="function"><span class="keyword">function</span>(<span class="params">...</span>)</span>&#123;...&#125;</span><br></pre></td></tr></table></figure>

<p>确定 <code>constructor</code> 属性是什么函数，可以使用 <code>name</code> 属性，从实例得到构造函数的名称。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Foo</span> (<span class="params"></span>) </span>&#123; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> f = <span class="keyword">new</span> Foo()</span><br><span class="line"></span><br><span class="line">f.constructor.name <span class="comment">// "Foo"</span></span><br></pre></td></tr></table></figure>

<h3 id="instanceof-运算符"><a href="#instanceof-运算符" class="headerlink" title="instanceof 运算符"></a>instanceof 运算符</h3><p>==<code>instanceof</code> 运算符返回一个布尔值，表示对象是否是某个构造函数的实例。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> p = <span class="keyword">new</span> Person();</span><br><span class="line"></span><br><span class="line">p <span class="keyword">instanceof</span> Person <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>==由于 <code>instanceof</code> 检查整个原型链，因此同一个实例对象，可能会对多个构造函数都返回 <code>true</code>。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> d = <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br><span class="line"></span><br><span class="line">d <span class="keyword">instanceof</span> <span class="built_in">Date</span> <span class="comment">// true</span></span><br><span class="line">d <span class="keyword">instanceof</span> <span class="built_in">Object</span> <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>==<code>instanceof</code> 运算符只能适用于对象，不适用于原始类型的值。==</p>
<h3 id="构造函数继承"><a href="#构造函数继承" class="headerlink" title="构造函数继承"></a>构造函数继承</h3><h4 id="思考"><a href="#思考" class="headerlink" title="思考"></a>思考</h4><p>现在有一个”动物”对象的构造函数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Animal</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">　<span class="keyword">this</span>.species = <span class="string">"动物"</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>还有一个”猫”对象的构造函数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Cat</span>(<span class="params">name,color</span>)</span>&#123;</span><br><span class="line">　　<span class="keyword">this</span>.name = name;</span><br><span class="line">　　<span class="keyword">this</span>.color = color;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>怎样才能使”猫”继承”动物”呢？</p>
<h4 id="一、构造函数绑定"><a href="#一、构造函数绑定" class="headerlink" title="一、构造函数绑定"></a>一、构造函数绑定</h4><p>第一种方法也是最简单的方法，使用 <code>call</code> 或 <code>apply</code> 方法，将父对象的构造函数绑定在子对象上，即在子对象构造函数中加一行：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">Cat</span>(<span class="params">name,color</span>)</span>&#123;</span><br><span class="line"></span><br><span class="line">　　　　Animal.apply(<span class="keyword">this</span>, <span class="built_in">arguments</span>);</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">this</span>.name = name;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">this</span>.color = color;</span><br><span class="line"></span><br><span class="line">　　&#125;</span><br><span class="line"></span><br><span class="line">　　<span class="keyword">var</span> cat1 = <span class="keyword">new</span> Cat(<span class="string">"大毛"</span>,<span class="string">"黄色"</span>);</span><br><span class="line"></span><br><span class="line">　　alert(cat1.species); <span class="comment">// 动物</span></span><br></pre></td></tr></table></figure>

<h4 id="二、prototype-模式"><a href="#二、prototype-模式" class="headerlink" title="二、prototype 模式"></a>二、prototype 模式</h4><p>第二种方法更常见，使用 <code>prototype</code> 属性。</p>
<p>如果”猫”的 <code>prototype</code> 对象，指向一个 <code>Animal</code> 的实例，那么所有”猫”的实例，就能继承 <code>Animal</code> 了。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">　　Cat.prototype = <span class="keyword">new</span> Animal();</span><br><span class="line"></span><br><span class="line">　　Cat.prototype.constructor = Cat;</span><br><span class="line"></span><br><span class="line">　　<span class="keyword">var</span> cat1 = <span class="keyword">new</span> Cat(<span class="string">"大毛"</span>,<span class="string">"黄色"</span>);</span><br><span class="line"></span><br><span class="line">　　alert(cat1.species); <span class="comment">// 动物</span></span><br></pre></td></tr></table></figure>

<p>代码的第一行，我们将 <code>Cat</code> 的 <code>prototype</code> 对象指向一个 <code>Animal</code> 的实例。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　Cat.prototype = <span class="keyword">new</span> Animal();</span><br></pre></td></tr></table></figure>

<p>它相当于完全删除了 <code>prototype</code> 对象原先的值，然后赋予一个新值。但是，第二行又是什么意思呢？</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　Cat.prototype.constructor = Cat;</span><br></pre></td></tr></table></figure>

<p>原来，任何一个 <code>prototype</code> 对象都有一个 <code>constructor</code> 属性，指向它的构造函数。如果没有 <code>&quot;Cat.prototype = new Animal();&quot;</code> 这一行，<code>Cat.prototype.constructor</code> 是指向 <code>Cat</code> 的；加了这一行以后，<code>Cat.prototype.constructor</code> 指向 <code>Animal</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　alert(Cat.prototype.constructor == Animal); <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<p>更重要的是，每一个实例也有一个 <code>constructor</code> 属性，默认调用 <code>prototype</code> 对象的 <code>constructor</code> 属性。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　alert(cat1.constructor == Cat.prototype.constructor); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>因此，在运行 <code>&quot;Cat.prototype = new Animal();&quot;</code> 这一行之后，<code>cat1.constructor</code> 也指向 <code>Animal</code> ！</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　alert(cat1.constructor == Animal); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>这显然会导致继承链的紊乱（<code>cat1</code> 明明是用构造函数 <code>Cat</code> 生成的），因此我们必须手动纠正，将 <code>Cat.prototype</code> 对象的 <code>constructor</code> 值改为 <code>Cat</code>。这就是第二行的意思。</p>
<p>这是很重要的一点，编程时务必要遵守。下文都遵循这一点，即如果替换了 <code>prototype</code> 对象，</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　o.prototype = &#123;&#125;;</span><br></pre></td></tr></table></figure>

<p>那么，下一步必然是为新的 <code>prototype</code> 对象加上 <code>constructor</code> 属性，并将这个属性指回原来的构造函数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　o.prototype.constructor = o;</span><br></pre></td></tr></table></figure>

<h4 id="三、直接继承-prototype"><a href="#三、直接继承-prototype" class="headerlink" title="三、直接继承 prototype"></a>三、直接继承 prototype</h4><p>第三种方法是对第二种方法的改进。由于 <code>Animal</code> 对象中，不变的属性都可以直接写入 <code>Animal.prototype</code>。所以，我们也可以让 <code>Cat()</code> 跳过 <code>Animal()</code>，直接继承 <code>Animal.prototype</code>。</p>
<p>现在，我们先将 <code>Animal</code> 对象改写：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">Animal</span>(<span class="params"></span>)</span>&#123; &#125;</span><br><span class="line"></span><br><span class="line">　　Animal.prototype.species = <span class="string">"动物"</span>;</span><br></pre></td></tr></table></figure>

<p>然后，将 <code>Cat</code> 的 <code>prototype</code> 对象，然后指向 <code>Animal</code> 的 <code>prototype</code> 对象，这样就完成了继承。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">　　Cat.prototype = Animal.prototype;</span><br><span class="line"></span><br><span class="line">　　Cat.prototype.constructor = Cat;</span><br><span class="line"></span><br><span class="line">　　<span class="keyword">var</span> cat1 = <span class="keyword">new</span> Cat(<span class="string">"大毛"</span>,<span class="string">"黄色"</span>);</span><br><span class="line"></span><br><span class="line">　　alert(cat1.species); <span class="comment">// 动物</span></span><br></pre></td></tr></table></figure>

<p>与前一种方法相比，这样做的优点是效率比较高（不用执行和建立 <code>Animal</code> 的实例了），比较省内存。缺点是  <code>Cat.prototype</code> 和 <code>Animal.prototype</code> 现在指向了同一个对象，那么任何对 <code>Cat.prototype</code> 的修改，都会反映到 <code>Animal.prototype</code>。</p>
<p>所以，上面这一段代码其实是有问题的。请看第二行</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　Cat.prototype.constructor = Cat;</span><br></pre></td></tr></table></figure>

<p>这一句实际上把 <code>Animal.prototype</code> 对象的 <code>constructor</code> 属性也改掉了！</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　alert(Animal.prototype.constructor); <span class="comment">// Cat</span></span><br></pre></td></tr></table></figure>

<h4 id="四、利用空对象作为中介"><a href="#四、利用空对象作为中介" class="headerlink" title="四、利用空对象作为中介"></a>四、利用空对象作为中介</h4><p>由于”直接继承 <code>prototype</code>“存在上述的缺点，所以就有第四种方法，利用一个空对象作为中介。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="keyword">var</span> F = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;;</span><br><span class="line"></span><br><span class="line">　　F.prototype = Animal.prototype;</span><br><span class="line"></span><br><span class="line">　　Cat.prototype = <span class="keyword">new</span> F();</span><br><span class="line"></span><br><span class="line">　　Cat.prototype.constructor = Cat;</span><br></pre></td></tr></table></figure>

<p><code>F</code> 是空对象，所以几乎不占内存。这时，修改 <code>Cat</code> 的 <code>prototype</code> 对象，就不会影响到 <code>Animal</code> 的 <code>prototype</code> 对象。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　alert(Animal.prototype.constructor); <span class="comment">// Animal</span></span><br></pre></td></tr></table></figure>

<p>我们将上面的方法，封装成一个函数，便于使用。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">extend</span>(<span class="params">Child, Parent</span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">var</span> F = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;&#125;;</span><br><span class="line"></span><br><span class="line">　　　　F.prototype = Parent.prototype;</span><br><span class="line"></span><br><span class="line">　　　　Child.prototype = <span class="keyword">new</span> F();</span><br><span class="line"></span><br><span class="line">　　　　Child.prototype.constructor = Child;</span><br><span class="line"></span><br><span class="line">　　　　Child.uber = Parent.prototype;</span><br><span class="line"></span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p>使用的时候，方法如下</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">　　extend(Cat,Animal);</span><br><span class="line"></span><br><span class="line">　　<span class="keyword">var</span> cat1 = <span class="keyword">new</span> Cat(<span class="string">"大毛"</span>,<span class="string">"黄色"</span>);</span><br><span class="line"></span><br><span class="line">　　alert(cat1.species); <span class="comment">// 动物</span></span><br></pre></td></tr></table></figure>

<p>这个 <code>extend</code> 函数，就是 <code>YUI</code> 库如何实现继承的方法。</p>
<p>另外，说明一点，函数体最后一行</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　Child.uber = Parent.prototype;</span><br></pre></td></tr></table></figure>

<p>意思是为子对象设一个 <code>uber</code> 属性，这个属性直接指向父对象的 <code>prototype</code> 属性。（<code>uber</code> 是一个德语词，意思是”向上”、”上一层”。）这等于在子对象上打开一条通道，可以直接调用父对象的方法。这一行放在这里，只是为了实现继承的完备性，纯属备用性质。</p>
<h4 id="五、拷贝继承"><a href="#五、拷贝继承" class="headerlink" title="五、拷贝继承"></a>五、拷贝继承</h4><p>上面是采用 <code>prototype</code> 对象，实现继承。我们也可以换一种思路，纯粹采用”拷贝”方法实现继承。简单说，如果把父对象的所有属性和方法，拷贝进子对象，不也能够实现继承吗？这样我们就有了第五种方法。</p>
<p>首先，还是把 <code>Animal</code> 的所有不变属性，都放到它的 <code>prototype</code> 对象上。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">Animal</span>(<span class="params"></span>)</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">　　Animal.prototype.species = <span class="string">"动物"</span>;</span><br></pre></td></tr></table></figure>

<p>然后，再写一个函数，实现属性拷贝的目的。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">extend2</span>(<span class="params">Child, Parent</span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">var</span> p = Parent.prototype;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">var</span> c = Child.prototype;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">for</span> (<span class="keyword">var</span> i <span class="keyword">in</span> p) &#123;</span><br><span class="line"></span><br><span class="line">　　　　　　c[i] = p[i];</span><br><span class="line"></span><br><span class="line">　　　　　　&#125;</span><br><span class="line"></span><br><span class="line">　　　　c.uber = p;</span><br><span class="line"></span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p>这个函数的作用，就是将父对象的 <code>prototype</code> 对象中的属性，一一拷贝给 <code>Child</code> 对象的 <code>prototype</code> 对象。</p>
<p>使用的时候，这样写：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">　　extend2(Cat, Animal);</span><br><span class="line"></span><br><span class="line">　　<span class="keyword">var</span> cat1 = <span class="keyword">new</span> Cat(<span class="string">"大毛"</span>,<span class="string">"黄色"</span>);</span><br><span class="line"></span><br><span class="line">　　alert(cat1.species); <span class="comment">// 动物</span></span><br></pre></td></tr></table></figure>

<h3 id="非构造函数继承"><a href="#非构造函数继承" class="headerlink" title="非构造函数继承"></a>非构造函数继承</h3><h4 id="思考-1"><a href="#思考-1" class="headerlink" title="思考"></a>思考</h4><p>什么是”非构造函数”的继承？</p>
<p>比如，现在有一个对象，叫做”中国人”。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="keyword">var</span> Chinese = &#123;</span><br><span class="line">　　　　nation:<span class="string">'中国'</span></span><br><span class="line">　　&#125;;</span><br></pre></td></tr></table></figure>

<p>还有一个对象，叫做”医生”。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="keyword">var</span> Doctor =&#123;</span><br><span class="line">　　　　career:<span class="string">'医生'</span></span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p>请问怎样才能让”医生”去继承”中国人”，也就是说，我怎样才能生成一个”中国医生”的对象？</p>
<p>这里要注意，这两个对象都是普通对象，不是构造函数，无法使用构造函数方法实现”继承”。</p>
<h4 id="一、object-方法"><a href="#一、object-方法" class="headerlink" title="一、object() 方法"></a>一、object() 方法</h4><p><code>json</code> 格式的发明人 Douglas Crockford，提出了一个 <code>object()</code> 函数，可以做到这一点。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">object</span>(<span class="params">o</span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">　　　　<span class="function"><span class="keyword">function</span> <span class="title">F</span>(<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">　　　　F.prototype = o;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">return</span> <span class="keyword">new</span> F();</span><br><span class="line"></span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p>这个 <code>object()</code> 函数，其实只做一件事，就是把子对象的 <code>prototype</code> 属性，指向父对象，从而使得子对象与父对象连在一起。</p>
<p>使用的时候，第一步先在父对象的基础上，生成子对象：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="keyword">var</span> Doctor = object(Chinese);</span><br></pre></td></tr></table></figure>

<p>然后，再加上子对象本身的属性：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　Doctor.career = <span class="string">'医生'</span>;</span><br></pre></td></tr></table></figure>

<p>这时，子对象已经继承了父对象的属性了。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　alert(Doctor.nation); <span class="comment">//中国</span></span><br></pre></td></tr></table></figure>

<h4 id="二、浅拷贝"><a href="#二、浅拷贝" class="headerlink" title="二、浅拷贝"></a>二、浅拷贝</h4><p>除了使用 <code>&quot;prototype链&quot;</code> 以外，还有另一种思路：把父对象的属性，全部拷贝给子对象，也能实现继承。</p>
<p>下面这个函数，就是在做拷贝：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">extendCopy</span>(<span class="params">p</span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">var</span> c = &#123;&#125;;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">for</span> (<span class="keyword">var</span> i <span class="keyword">in</span> p) &#123; </span><br><span class="line">　　　　　　c[i] = p[i];</span><br><span class="line">　　　　&#125;</span><br><span class="line"></span><br><span class="line">　　　　c.uber = p;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">return</span> c;</span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p>使用的时候，这样写：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="keyword">var</span> Doctor = extendCopy(Chinese);</span><br><span class="line"></span><br><span class="line">　　Doctor.career = <span class="string">'医生'</span>;</span><br><span class="line"></span><br><span class="line">　　alert(Doctor.nation); <span class="comment">// 中国</span></span><br></pre></td></tr></table></figure>

<p>但是，这样的拷贝有一个问题。那就是，如果父对象的属性等于数组或另一个对象，那么实际上，子对象获得的只是一个内存地址，而不是真正拷贝，因此存在父对象被篡改的可能。</p>
<p>请看，现在给 <code>Chinese</code> 添加一个”出生地”属性，它的值是一个数组。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　Chinese.birthPlaces = [<span class="string">'北京'</span>,<span class="string">'上海'</span>,<span class="string">'香港'</span>];</span><br></pre></td></tr></table></figure>

<p>通过 <code>extendCopy()</code> 函数，<code>Doctor</code> 继承了 <code>Chinese</code>。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="keyword">var</span> Doctor = extendCopy(Chinese);</span><br></pre></td></tr></table></figure>

<p>然后，我们为 <code>Doctor</code> 的”出生地”添加一个城市：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　Doctor.birthPlaces.push(<span class="string">'厦门'</span>);</span><br></pre></td></tr></table></figure>

<p>发生了什么事？<code>Chinese</code> 的”出生地”也被改掉了！</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">　　alert(Doctor.birthPlaces); <span class="comment">//北京, 上海, 香港, 厦门</span></span><br><span class="line"></span><br><span class="line">　　alert(Chinese.birthPlaces); <span class="comment">//北京, 上海, 香港, 厦门</span></span><br></pre></td></tr></table></figure>

<p>所以，<code>extendCopy()</code> 只是拷贝基本类型的数据，我们把这种拷贝叫做”浅拷贝”。这是早期 <code>jQuery</code> 实现继承的方式。</p>
<h4 id="三、深拷贝"><a href="#三、深拷贝" class="headerlink" title="三、深拷贝"></a>三、深拷贝</h4><p>所谓”深拷贝”，就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难，只要递归调用”浅拷贝”就行了。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="function"><span class="keyword">function</span> <span class="title">deepCopy</span>(<span class="params">p, c</span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">var</span> c = c || &#123;&#125;;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">for</span> (<span class="keyword">var</span> i <span class="keyword">in</span> p) &#123;</span><br><span class="line"></span><br><span class="line">　　　　　　<span class="keyword">if</span> (<span class="keyword">typeof</span> p[i] === <span class="string">'object'</span>) &#123;</span><br><span class="line"></span><br><span class="line">　　　　　　　　c[i] = (p[i].constructor === <span class="built_in">Array</span>) ? [] : &#123;&#125;;</span><br><span class="line"></span><br><span class="line">　　　　　　　　deepCopy(p[i], c[i]);</span><br><span class="line"></span><br><span class="line">　　　　　　&#125; <span class="keyword">else</span> &#123;</span><br><span class="line"></span><br><span class="line">　　　　　　　　　c[i] = p[i];</span><br><span class="line"></span><br><span class="line">　　　　　　&#125;</span><br><span class="line">　　　　&#125;</span><br><span class="line"></span><br><span class="line">　　　　<span class="keyword">return</span> c;</span><br><span class="line">　　&#125;</span><br></pre></td></tr></table></figure>

<p>使用的时候这样写：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">　　<span class="keyword">var</span> Doctor = deepCopy(Chinese);</span><br></pre></td></tr></table></figure>

<p>现在，给父对象加一个属性，值为数组。然后，在子对象上修改这个属性：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">　　Chinese.birthPlaces = [<span class="string">'北京'</span>,<span class="string">'上海'</span>,<span class="string">'香港'</span>];</span><br><span class="line"></span><br><span class="line">　　Doctor.birthPlaces.push(<span class="string">'厦门'</span>);</span><br></pre></td></tr></table></figure>

<p>这时，父对象就不会受到影响了。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">　　alert(Doctor.birthPlaces); <span class="comment">//北京, 上海, 香港, 厦门</span></span><br><span class="line"></span><br><span class="line">　　alert(Chinese.birthPlaces); <span class="comment">//北京, 上海, 香港</span></span><br></pre></td></tr></table></figure>

<p>目前，<code>jQuery</code> 库使用的就是这种继承方法。</p>
<h3 id="多重继承"><a href="#多重继承" class="headerlink" title="多重继承"></a>多重继承</h3><p>JavaScript 不提供多重继承功能，即不允许一个对象同时继承多个对象。但是，可以通过变通方法，实现这个功能。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">M1</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">this</span>.hello = <span class="string">'hello'</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">M2</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">this</span>.world = <span class="string">'world'</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">S</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  M1.call(<span class="keyword">this</span>);</span><br><span class="line">  M2.call(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 继承 M1</span></span><br><span class="line">S.prototype = <span class="built_in">Object</span>.create(M1.prototype);</span><br><span class="line"><span class="comment">// 继承链上加入 M2</span></span><br><span class="line"><span class="built_in">Object</span>.assign(S.prototype, M2.prototype);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 指定构造函数</span></span><br><span class="line">S.prototype.constructor = S;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> S();</span><br><span class="line">s.hello <span class="comment">// 'hello'</span></span><br><span class="line">s.world <span class="comment">// 'world'</span></span><br></pre></td></tr></table></figure>

<p>上面代码中，子类S同时继承了父类 M1 和 M2 。这种模式又称为 <code>Mixin</code>（混入）。</p>
<h2 id="模块"><a href="#模块" class="headerlink" title="模块"></a>模块</h2><p>JavaScript 不是一种模块化编程语言，ES6 才开始支持“类”和“模块”。下面介绍传统的做法，如何利用对象实现模块的效果。</p>
<h3 id="基本的实现方法"><a href="#基本的实现方法" class="headerlink" title="基本的实现方法"></a>基本的实现方法</h3><p>模块是实现特定功能的一组属性和方法的封装。</p>
<p>简单的做法是把模块写成一个对象，所有的模块成员都放到这个对象里面。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> module1 = <span class="keyword">new</span> <span class="built_in">Object</span>(&#123;</span><br><span class="line">　_count : <span class="number">0</span>,</span><br><span class="line">　m1 : <span class="function"><span class="keyword">function</span> (<span class="params"></span>)</span>&#123;</span><br><span class="line">　　<span class="comment">//...</span></span><br><span class="line">　&#125;,</span><br><span class="line">　m2 : <span class="function"><span class="keyword">function</span> (<span class="params"></span>)</span>&#123;</span><br><span class="line">  　<span class="comment">//...</span></span><br><span class="line">　&#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>上面的函数 <code>m1</code> 和 <code>m2</code>，都封装在 <code>module1</code> 对象里。使用的时候，就是调用这个对象的属性。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">module1.m1();</span><br></pre></td></tr></table></figure>

<p>但是，这样的写法会暴露所有模块成员，内部状态可以被外部改写。比如，外部代码可以直接改变内部计数器的值。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">module1._count = <span class="number">5</span>;</span><br></pre></td></tr></table></figure>

<h3 id="封装私有变量：构造函数的写法"><a href="#封装私有变量：构造函数的写法" class="headerlink" title="封装私有变量：构造函数的写法"></a>封装私有变量：构造函数的写法</h3><p>利用构造函数，封装私有变量。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">StringBuilder</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> buffer = [];</span><br><span class="line"></span><br><span class="line">  <span class="keyword">this</span>.add = <span class="function"><span class="keyword">function</span> (<span class="params">str</span>) </span>&#123;</span><br><span class="line">     buffer.push(str);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">this</span>.toString = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> buffer.join(<span class="string">''</span>);</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这种方式一旦生成实例对象，外部是无法直接访问 <code>buffer</code> 的。但是，这种方法将私有变量封装在构造函数中，导致构造函数与实例对象是一体的，总是存在于内存之中，无法在使用完成后清除。这意味着，构造函数有双重作用，既用来塑造实例对象，又用来保存实例对象的数据，违背了构造函数与实例对象在数据上相分离的原则（即实例对象的数据，不应该保存在实例对象以外）。同时，非常耗费内存。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">StringBuilder</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">this</span>._buffer = [];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">StringBuilder.prototype = &#123;</span><br><span class="line">  <span class="keyword">constructor</span>: StringBuilder,</span><br><span class="line">  add: function (str) &#123;</span><br><span class="line">    <span class="keyword">this</span>._buffer.push(str);</span><br><span class="line">  &#125;,</span><br><span class="line">  toString: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">this</span>._buffer.join(<span class="string">''</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>这种方法将私有变量放入实例对象中，好处是看上去更自然，但是它的私有变量可以从外部读写，不是很安全。</p>
<h3 id="封装私有变量：立即执行函数的写法"><a href="#封装私有变量：立即执行函数的写法" class="headerlink" title="封装私有变量：立即执行函数的写法"></a>封装私有变量：立即执行函数的写法</h3><p>另一种做法是使用“立即执行函数”，将相关的属性和方法封装在一个函数作用域里面，可以达到不暴露私有成员的目的。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> module1 = (<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">　<span class="keyword">var</span> _count = <span class="number">0</span>;</span><br><span class="line">　<span class="keyword">var</span> m1 = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">　  <span class="comment">//...</span></span><br><span class="line">　&#125;;</span><br><span class="line">　<span class="keyword">var</span> m2 = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">　　<span class="comment">//...</span></span><br><span class="line">　&#125;;</span><br><span class="line">　<span class="keyword">return</span> &#123;</span><br><span class="line">　　m1 : m1,</span><br><span class="line">　　m2 : m2</span><br><span class="line">　&#125;;</span><br><span class="line">&#125;)();</span><br></pre></td></tr></table></figure>

<p>使用上面的写法，外部代码无法读取内部的 <code>_count</code> 变量。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.info(module1._count); <span class="comment">//undefined</span></span><br></pre></td></tr></table></figure>

<p>上面的 <code>module1</code> 就是 JavaScript 模块的基本写法。</p>
<h3 id="模块的放大模式"><a href="#模块的放大模式" class="headerlink" title="模块的放大模式"></a>模块的放大模式</h3><p>如果一个模块很大，必须分成几个部分，或者一个模块需要继承另一个模块，这时就有必要采用“放大模式”。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> module1 = (<span class="function"><span class="keyword">function</span> (<span class="params">mod</span>)</span>&#123;</span><br><span class="line">　mod.m3 = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">　　<span class="comment">//...</span></span><br><span class="line">　&#125;;</span><br><span class="line">　<span class="keyword">return</span> mod;</span><br><span class="line">&#125;)(module1);</span><br></pre></td></tr></table></figure>

<p>上面的代码为 <code>module1</code> 模块添加了一个新方法 <code>m3()</code>，然后返回新的module1模块。</p>
<h3 id="输入全局变量"><a href="#输入全局变量" class="headerlink" title="输入全局变量"></a>输入全局变量</h3><p>独立性是模块的重要特点，模块内部最好不与程序的其他部分直接交互。</p>
<p>为了在模块内部调用全局变量，必须显式地将其他变量输入模块。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> module1 = (<span class="function"><span class="keyword">function</span> (<span class="params">$, YAHOO</span>) </span>&#123;</span><br><span class="line">　<span class="comment">//...</span></span><br><span class="line">&#125;)(jQuery, YAHOO);</span><br></pre></td></tr></table></figure>

<p>上面的 <code>module1</code> 模块需要使用 jQuery 库和 YUI 库，就把这两个库（其实是两个模块）当作参数输入 <code>module1</code>。这样做除了保证模块的独立性，还使得模块之间的依赖关系变得明显。</p>
<h2 id="Object-对象的相关方法"><a href="#Object-对象的相关方法" class="headerlink" title="Object 对象的相关方法"></a>Object 对象的相关方法</h2><p>关于面向对象编程，<code>Object</code> 对象也提供了相关的方法。</p>
<h3 id="Object-getPrototypeOf"><a href="#Object-getPrototypeOf" class="headerlink" title="Object.getPrototypeOf()"></a>Object.getPrototypeOf()</h3><p>==<code>Object.getPrototypeOf</code> 方法返回参数对象的原型。这是获取原型对象的标准方法。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> F = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> f = <span class="keyword">new</span> F();</span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.getPrototypeOf(f) === F.prototype <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h3 id="Object-setPrototypeOf"><a href="#Object-setPrototypeOf" class="headerlink" title="Object.setPrototypeOf()"></a>Object.setPrototypeOf()</h3><p>==<code>Object.setPrototypeOf</code> 方法为参数对象设置原型，返回该参数对象。它接受两个参数，第一个是现有对象，第二个是原型对象。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> a = &#123; &#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> b = &#123;<span class="attr">x</span>:<span class="number">1</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.setPrototypeOf(a,b);</span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.getPrototypeOf(a) === b <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">a.x <span class="comment">// 1</span></span><br></pre></td></tr></table></figure>

<h3 id="Object-create"><a href="#Object-create" class="headerlink" title="Object.create()"></a>Object.create()</h3><p><code>Object.create</code> 方法可以实现从一个实例对象，生成另一个实例对象。该方法接受一个对象作为参数，然后以它为原型，返回一个实例对象。==该实例对象完全继承原型对象的属性。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 原型对象</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> A = &#123;</span><br><span class="line">    print:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">'hello'</span>)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 实例对象</span></span><br><span class="line"><span class="keyword">var</span> B = <span class="built_in">Object</span>.create(A)</span><br><span class="line"></span><br><span class="line"><span class="built_in">Object</span>.getPrototypeOf(B) === A <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">B.print() <span class="comment">// hello</span></span><br><span class="line">B.print === A.print <span class="comment">//true</span></span><br></pre></td></tr></table></figure>

<p>下面三种方式生成的新对象是等价的。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj1 = <span class="built_in">Object</span>.create(&#123;&#125;)</span><br><span class="line"><span class="keyword">var</span> obj2 = <span class="built_in">Object</span>.create(<span class="built_in">Object</span>.prototype)</span><br><span class="line"><span class="keyword">var</span> obj3 = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br></pre></td></tr></table></figure>

<p>==如果想要生成一个不继承任何属性（比如没有 <code>toString</code> 和 <code>valueOf</code> 方法）的对象，可以将 <code>Object.create</code> 的参数设为 <code>null</code> 。==</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = <span class="built_in">Object</span>.create(<span class="literal">null</span>)</span><br><span class="line"></span><br><span class="line">obj.valueOf() <span class="comment">// TypeError: Object [object Object] has no method 'valueOf'</span></span><br></pre></td></tr></table></figure>

<h3 id="Object-prototype-isPrototypeOf"><a href="#Object-prototype-isPrototypeOf" class="headerlink" title="Object.prototype.isPrototypeOf"></a>Object.prototype.isPrototypeOf</h3><p>实例对象的 <code>isPrototypeOf</code> 方法，用来判断该对象是否为参数对象的原型。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> o1 = &#123;&#125;</span><br><span class="line"><span class="keyword">var</span> o2 = <span class="built_in">Object</span>.create(o1);</span><br><span class="line"><span class="keyword">var</span> o3 = <span class="built_in">Object</span>.create(o2);</span><br><span class="line"></span><br><span class="line">o2.isPrototypeOf(o3) <span class="comment">// true</span></span><br><span class="line">o1.isPrototypeOf(o2) <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h3 id="Object-prototype-proto"><a href="#Object-prototype-proto" class="headerlink" title="Object.prototype.__proto__"></a><code>Object.prototype.__proto__</code></h3><p>实例对象的属性（前后两个下划线）<code>__proto__</code> ，返回该对象的原型，该属性可读写。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = &#123;&#125;</span><br><span class="line"><span class="keyword">var</span> p = &#123;&#125;</span><br><span class="line"></span><br><span class="line">obj.__proto__ = p</span><br><span class="line"><span class="built_in">Object</span>.getPrototypeOf(obj) === p <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<h3 id="获取原型对象方法比较"><a href="#获取原型对象方法比较" class="headerlink" title="获取原型对象方法比较"></a>获取原型对象方法比较</h3><p>获取实例对象 <code>obj</code> 的原型对象，有三种方法：</p>
<ul>
<li><code>obj.__proto__</code></li>
<li><code>obj.constructor.prototype</code></li>
<li><code>Object.getPrototypeOf(obj)</code></li>
</ul>
<p>==三种方法中，<code>__proto__</code> 只有浏览器才需要部署，其它环境可以不部署。而 <code>obj.constructor.prototype</code> 在手动改变原型对象时，有可能失效。推荐使用第三种 <code>Object.getPrototypeOf</code> 方法，获取原型对象。==</p>
<h2 id="对象的拷贝"><a href="#对象的拷贝" class="headerlink" title="对象的拷贝"></a>对象的拷贝</h2><p>拷贝一个对象，需要做到下面两点：</p>
<ul>
<li>确保拷贝后的对象，与原对象具有同样的原型</li>
<li>确保拷贝后的对象，与原对象具有同样的实例属性</li>
</ul>
<hr>
<h1 id="定时器"><a href="#定时器" class="headerlink" title="定时器"></a>定时器</h1><h2 id="setTimeout"><a href="#setTimeout" class="headerlink" title="setTimeout()"></a>setTimeout()</h2><p><code>setTimeout</code> 函数用来指定某个函数或某段代码，在多少毫秒之后执行。它返回一个整数，表示定时器的编号，以后可以用来取消这个定时器。</p>
<p><code>setTimeout</code> 函数接受两个参数，第一个参数 <code>func|code</code> 是将要推迟执行的函数名或者一段代码，第二个参数 <code>delay</code> 是推迟执行的毫秒数。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> timerId = setTimeout(func|code,delay);</span><br></pre></td></tr></table></figure>

<h2 id="setInterval"><a href="#setInterval" class="headerlink" title="setInterval()"></a>setInterval()</h2><p><code>setInterval</code> 函数的用法与 <code>setTimeout</code> 完全一致，区别仅在于 <code>setInterval</code> 指定某个任务每隔一段时间就执行一次，也就是无限次的定时执行。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> i = <span class="number">1</span></span><br><span class="line"><span class="keyword">var</span> timer = setInterval(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="number">2</span>);</span><br><span class="line">&#125;, <span class="number">1000</span>)</span><br></pre></td></tr></table></figure>

<h2 id="clearTimeout-、clearInterval"><a href="#clearTimeout-、clearInterval" class="headerlink" title="clearTimeout()、clearInterval()"></a>clearTimeout()、clearInterval()</h2><p><code>setTimeout</code> 和 <code>setInterval</code> 函数，都返回一个整数值，表示计数器编号。将该整数编号传入 <code>clearTimeout</code> 和 <code>clearInterval</code> 函数，就可以取消对应的定时器。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> id1 = setTimeout(f,<span class="number">1000</span>);</span><br><span class="line"><span class="keyword">var</span> id2 = setInterval(f,<span class="number">1000</span>);</span><br><span class="line"></span><br><span class="line">clearTimeout(id1);</span><br><span class="line">clearInterval(id2);</span><br></pre></td></tr></table></figure>


      </div>
      
      
      
    </div>
    

    
    
    


          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#基本语法"><span class="nav-number">1.</span> <span class="nav-text">基本语法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#语句"><span class="nav-number">1.1.</span> <span class="nav-text">语句</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#变量"><span class="nav-number">1.2.</span> <span class="nav-text">变量</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#概念"><span class="nav-number">1.2.1.</span> <span class="nav-text">概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#变量提升"><span class="nav-number">1.2.2.</span> <span class="nav-text">变量提升</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#标识符"><span class="nav-number">1.3.</span> <span class="nav-text">标识符</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#注释"><span class="nav-number">1.4.</span> <span class="nav-text">注释</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#区块"><span class="nav-number">1.5.</span> <span class="nav-text">区块</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#条件语句"><span class="nav-number">1.6.</span> <span class="nav-text">条件语句</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#if-结构"><span class="nav-number">1.6.1.</span> <span class="nav-text">if 结构</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#if-…-else-结构"><span class="nav-number">1.6.2.</span> <span class="nav-text">if … else 结构</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#switch-结构"><span class="nav-number">1.6.3.</span> <span class="nav-text">switch 结构</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#三元运算符"><span class="nav-number">1.6.4.</span> <span class="nav-text">三元运算符 ? :</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#循环语句"><span class="nav-number">1.7.</span> <span class="nav-text">循环语句</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#while-循环"><span class="nav-number">1.7.1.</span> <span class="nav-text">while 循环</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#for-循环"><span class="nav-number">1.7.2.</span> <span class="nav-text">for 循环</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#do-…-while-循环"><span class="nav-number">1.7.3.</span> <span class="nav-text">do … while 循环</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#break-语句和-continue-语句"><span class="nav-number">1.7.4.</span> <span class="nav-text">break 语句和 continue 语句</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#数据类型"><span class="nav-number">2.</span> <span class="nav-text">数据类型</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#数据分类"><span class="nav-number">2.1.</span> <span class="nav-text">数据分类</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#判断数据类型"><span class="nav-number">2.2.</span> <span class="nav-text">判断数据类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#null-undefined-和布尔值"><span class="nav-number">2.3.</span> <span class="nav-text">null, undefined 和布尔值</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#null-和-undefined"><span class="nav-number">2.3.1.</span> <span class="nav-text">null 和 undefined</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#布尔值"><span class="nav-number">2.3.2.</span> <span class="nav-text">布尔值</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#数值"><span class="nav-number">2.4.</span> <span class="nav-text">数值</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#NaN"><span class="nav-number">2.4.1.</span> <span class="nav-text">NaN</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#parseInt"><span class="nav-number">2.4.2.</span> <span class="nav-text">parseInt()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#parseFloat"><span class="nav-number">2.4.3.</span> <span class="nav-text">parseFloat()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#isNaN"><span class="nav-number">2.4.4.</span> <span class="nav-text">isNaN()</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#字符串"><span class="nav-number">2.5.</span> <span class="nav-text">字符串</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#转义"><span class="nav-number">2.5.1.</span> <span class="nav-text">转义</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#字符串与数组"><span class="nav-number">2.5.2.</span> <span class="nav-text">字符串与数组</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#length-属性"><span class="nav-number">2.5.3.</span> <span class="nav-text">length 属性</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#对象"><span class="nav-number">2.6.</span> <span class="nav-text">对象</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#键名"><span class="nav-number">2.6.1.</span> <span class="nav-text">键名</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#对象的引用"><span class="nav-number">2.6.2.</span> <span class="nav-text">对象的引用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#表达式还是语句？"><span class="nav-number">2.6.3.</span> <span class="nav-text">表达式还是语句？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#属性操作"><span class="nav-number">2.6.4.</span> <span class="nav-text">属性操作</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#属性读取"><span class="nav-number">2.6.4.1.</span> <span class="nav-text">属性读取</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#属性赋值"><span class="nav-number">2.6.4.2.</span> <span class="nav-text">属性赋值</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#属性的查看"><span class="nav-number">2.6.4.3.</span> <span class="nav-text">属性的查看</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#属性的删除：delete-命令"><span class="nav-number">2.6.4.4.</span> <span class="nav-text">属性的删除：delete 命令</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#属性是否存在：in-运算符"><span class="nav-number">2.6.4.5.</span> <span class="nav-text">属性是否存在：in 运算符</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#属性的遍历：for…in-循环"><span class="nav-number">2.6.4.6.</span> <span class="nav-text">属性的遍历：for…in 循环</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#函数"><span class="nav-number">2.7.</span> <span class="nav-text">函数</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#函数的声明"><span class="nav-number">2.7.1.</span> <span class="nav-text">函数的声明</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#圆括号运算符，return-语句"><span class="nav-number">2.7.2.</span> <span class="nav-text">圆括号运算符，return 语句</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#递归"><span class="nav-number">2.7.3.</span> <span class="nav-text">递归</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数名的提升"><span class="nav-number">2.7.4.</span> <span class="nav-text">函数名的提升</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数的属性和方法"><span class="nav-number">2.7.5.</span> <span class="nav-text">函数的属性和方法</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#name"><span class="nav-number">2.7.5.1.</span> <span class="nav-text">name</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#length-属性-1"><span class="nav-number">2.7.5.2.</span> <span class="nav-text">length 属性</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#toString-NaN"><span class="nav-number">2.7.5.3.</span> <span class="nav-text">toString()</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#函数作用域"><span class="nav-number">2.7.6.</span> <span class="nav-text">函数作用域</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#定义"><span class="nav-number">2.7.6.1.</span> <span class="nav-text">定义</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#函数内部的变量提升"><span class="nav-number">2.7.6.2.</span> <span class="nav-text">函数内部的变量提升</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#函数本身的作用域"><span class="nav-number">2.7.6.3.</span> <span class="nav-text">函数本身的作用域</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#参数"><span class="nav-number">2.7.7.</span> <span class="nav-text">参数</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#概述"><span class="nav-number">2.7.7.1.</span> <span class="nav-text">概述</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#传递方式"><span class="nav-number">2.7.7.2.</span> <span class="nav-text">传递方式</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#闭包"><span class="nav-number">2.7.8.</span> <span class="nav-text">闭包</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#立即调用的函数表达式（IIFE）"><span class="nav-number">2.7.9.</span> <span class="nav-text">立即调用的函数表达式（IIFE）</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#变量的声明"><span class="nav-number">3.</span> <span class="nav-text">变量的声明</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#ES-5-1"><span class="nav-number">3.1.</span> <span class="nav-text">ES 5.1</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#ES-6"><span class="nav-number">3.2.</span> <span class="nav-text">ES 6</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#运算符"><span class="nav-number">4.</span> <span class="nav-text">运算符</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#取反运算符（-）"><span class="nav-number">4.1.</span> <span class="nav-text">取反运算符（!）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#或运算符（a-b）"><span class="nav-number">4.2.</span> <span class="nav-text">或运算符（a || b）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#且运算符（a-amp-amp-b）"><span class="nav-number">4.3.</span> <span class="nav-text">且运算符（a &amp;&amp; b）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#和"><span class="nav-number">4.4.</span> <span class="nav-text">&#x3D;&#x3D; 和 &#x3D;&#x3D;&#x3D;</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#三元条件运算符（a-b-c）"><span class="nav-number">4.5.</span> <span class="nav-text">三元条件运算符（a ? b : c）</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#自增和自减"><span class="nav-number">4.6.</span> <span class="nav-text">自增和自减</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#数据类型转换"><span class="nav-number">5.</span> <span class="nav-text">数据类型转换</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#强制转换"><span class="nav-number">5.1.</span> <span class="nav-text">强制转换</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#自动转换"><span class="nav-number">5.2.</span> <span class="nav-text">自动转换</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#自动转换为布尔值"><span class="nav-number">5.2.1.</span> <span class="nav-text">自动转换为布尔值</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#自动转换为字符串"><span class="nav-number">5.2.2.</span> <span class="nav-text">自动转换为字符串</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#自动转换为数值"><span class="nav-number">5.2.3.</span> <span class="nav-text">自动转换为数值</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#String-常见用法"><span class="nav-number">6.</span> <span class="nav-text">String 常见用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#String-prototype-slice"><span class="nav-number">6.1.</span> <span class="nav-text">String.prototype.slice()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#String-prototype-substring-、String-prototype-substr"><span class="nav-number">6.2.</span> <span class="nav-text">String.prototype.substring()、String.prototype.substr()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#String-prototype-indexOf-、String-prototype-lastIndexOf"><span class="nav-number">6.3.</span> <span class="nav-text">String.prototype.indexOf()、String.prototype.lastIndexOf()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#String-prototype-trim"><span class="nav-number">6.4.</span> <span class="nav-text">String.prototype.trim()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#String-prototype-toLowerCase-、toUpperCase"><span class="nav-number">6.5.</span> <span class="nav-text">String.prototype.toLowerCase()、toUpperCase()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#String-prototype-match"><span class="nav-number">6.6.</span> <span class="nav-text">String.prototype.match()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#String-prorotype-search"><span class="nav-number">6.7.</span> <span class="nav-text">String.prorotype.search()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#String-prototype-replace"><span class="nav-number">6.8.</span> <span class="nav-text">String.prototype.replace()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#String-prototype-split"><span class="nav-number">6.9.</span> <span class="nav-text">String.prototype.split()</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Number-常见用法"><span class="nav-number">7.</span> <span class="nav-text">Number 常见用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Number-prototype-toString"><span class="nav-number">7.1.</span> <span class="nav-text">Number.prototype.toString()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Number-prototype-toFiexd"><span class="nav-number">7.2.</span> <span class="nav-text">Number.prototype.toFiexd()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#全局方法-parseInt"><span class="nav-number">7.3.</span> <span class="nav-text">全局方法 parseInt()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#全局方法-parseFloat"><span class="nav-number">7.4.</span> <span class="nav-text">全局方法 parseFloat()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#NaN、全局方法-isNaN"><span class="nav-number">7.5.</span> <span class="nav-text">NaN、全局方法 isNaN()</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Array-常见用法"><span class="nav-number">8.</span> <span class="nav-text">Array 常见用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Array-isArray"><span class="nav-number">8.1.</span> <span class="nav-text">Array.isArray()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#push"><span class="nav-number">8.2.</span> <span class="nav-text">push()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#pop"><span class="nav-number">8.3.</span> <span class="nav-text">pop()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#shift"><span class="nav-number">8.4.</span> <span class="nav-text">shift()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#unshift"><span class="nav-number">8.5.</span> <span class="nav-text">unshift()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#join"><span class="nav-number">8.6.</span> <span class="nav-text">join()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#concat"><span class="nav-number">8.7.</span> <span class="nav-text">concat()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#slice"><span class="nav-number">8.8.</span> <span class="nav-text">slice()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#splice"><span class="nav-number">8.9.</span> <span class="nav-text">splice()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#indexOf-、lastIndexOf"><span class="nav-number">8.10.</span> <span class="nav-text">indexOf()、lastIndexOf()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#map"><span class="nav-number">8.11.</span> <span class="nav-text">map()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#forEach"><span class="nav-number">8.12.</span> <span class="nav-text">forEach()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#filter"><span class="nav-number">8.13.</span> <span class="nav-text">filter()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#in-运算符、for-…-in-循环"><span class="nav-number">8.14.</span> <span class="nav-text">in 运算符、for … in 循环</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#数组的遍历"><span class="nav-number">8.15.</span> <span class="nav-text">数组的遍历</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#类数组对象"><span class="nav-number">8.16.</span> <span class="nav-text">类数组对象</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Object-常见用法"><span class="nav-number">9.</span> <span class="nav-text">Object 常见用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#delete-命令"><span class="nav-number">9.1.</span> <span class="nav-text">delete 命令</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#in-运算符"><span class="nav-number">9.2.</span> <span class="nav-text">in 运算符</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#for-…-in-循环"><span class="nav-number">9.3.</span> <span class="nav-text">for … in 循环</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Object-keys-、Object-getOwnPropertyNames"><span class="nav-number">9.4.</span> <span class="nav-text">Object.keys()、Object.getOwnPropertyNames()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#toString-应用：判断数据类型"><span class="nav-number">9.5.</span> <span class="nav-text">toString()应用：判断数据类型</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Object-prototype-hasOwnProperty"><span class="nav-number">9.6.</span> <span class="nav-text">Object.prototype.hasOwnProperty()</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Math-用法"><span class="nav-number">10.</span> <span class="nav-text">Math 用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Math-abs"><span class="nav-number">10.1.</span> <span class="nav-text">Math.abs()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Math-max-、Math-min"><span class="nav-number">10.2.</span> <span class="nav-text">Math.max()、Math.min()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Math-floor-、Math-ceil"><span class="nav-number">10.3.</span> <span class="nav-text">Math.floor()、Math.ceil()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Math-round"><span class="nav-number">10.4.</span> <span class="nav-text">Math.round()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Math-random"><span class="nav-number">10.5.</span> <span class="nav-text">Math.random()</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Date-对象常见用法"><span class="nav-number">11.</span> <span class="nav-text">Date 对象常见用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Date"><span class="nav-number">11.1.</span> <span class="nav-text">Date()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Date-now"><span class="nav-number">11.2.</span> <span class="nav-text">Date.now()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#get-类方法（set-）"><span class="nav-number">11.3.</span> <span class="nav-text">get 类方法（set*）</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#getTime"><span class="nav-number">11.3.1.</span> <span class="nav-text">getTime()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#getFullYear-、getMonth-、getDate-、getDay"><span class="nav-number">11.3.2.</span> <span class="nav-text">getFullYear()、getMonth()、getDate()、getDay()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#getHours-、getMinutes-、getSeconds"><span class="nav-number">11.3.3.</span> <span class="nav-text">getHours()、getMinutes()、getSeconds()</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Regexp-用法"><span class="nav-number">12.</span> <span class="nav-text">Regexp 用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#创建"><span class="nav-number">12.1.</span> <span class="nav-text">创建</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#RegExp-prototype-test"><span class="nav-number">12.2.</span> <span class="nav-text">RegExp.prototype.test()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#RegExp-prototype-exec"><span class="nav-number">12.3.</span> <span class="nav-text">RegExp.prototype.exec()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#字符串的实例方法"><span class="nav-number">12.4.</span> <span class="nav-text">字符串的实例方法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#String-prototype-match-1"><span class="nav-number">12.4.1.</span> <span class="nav-text">String.prototype.match()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#String-prototype-search"><span class="nav-number">12.4.2.</span> <span class="nav-text">String.prototype.search()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#String-prototype-replace-1"><span class="nav-number">12.4.3.</span> <span class="nav-text">String.prototype.replace()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#String-prototype-split-1"><span class="nav-number">12.4.4.</span> <span class="nav-text">String.prototype.split()</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#匹配规则"><span class="nav-number">12.5.</span> <span class="nav-text">匹配规则</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#字面量字符和元字符"><span class="nav-number">12.5.1.</span> <span class="nav-text">字面量字符和元字符</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#点字符（-）"><span class="nav-number">12.5.1.1.</span> <span class="nav-text">点字符（.）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#位置字符"><span class="nav-number">12.5.1.2.</span> <span class="nav-text">位置字符</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#选择符（-）"><span class="nav-number">12.5.1.3.</span> <span class="nav-text">选择符（|）</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#转义符"><span class="nav-number">12.5.2.</span> <span class="nav-text">转义符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#特殊字符"><span class="nav-number">12.5.3.</span> <span class="nav-text">特殊字符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#字符类"><span class="nav-number">12.5.4.</span> <span class="nav-text">字符类</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#脱字符（-）"><span class="nav-number">12.5.4.1.</span> <span class="nav-text">脱字符（^）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#连字符（-）"><span class="nav-number">12.5.4.2.</span> <span class="nav-text">连字符（-）</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#预定义模式"><span class="nav-number">12.5.5.</span> <span class="nav-text">预定义模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#重复类"><span class="nav-number">12.5.6.</span> <span class="nav-text">重复类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#量词符"><span class="nav-number">12.5.7.</span> <span class="nav-text">量词符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#贪婪模式"><span class="nav-number">12.5.8.</span> <span class="nav-text">贪婪模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#修饰符"><span class="nav-number">12.5.9.</span> <span class="nav-text">修饰符</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#g-修饰符"><span class="nav-number">12.5.9.1.</span> <span class="nav-text">g 修饰符</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#i-修饰符"><span class="nav-number">12.5.9.2.</span> <span class="nav-text">i 修饰符</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#m-修饰符"><span class="nav-number">12.5.9.3.</span> <span class="nav-text">m 修饰符</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#JSON-对象用法"><span class="nav-number">13.</span> <span class="nav-text">JSON 对象用法</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#JSON-stringify-、JSON-parse"><span class="nav-number">13.1.</span> <span class="nav-text">JSON.stringify()、JSON.parse()</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#面向对象编程"><span class="nav-number">14.</span> <span class="nav-text">面向对象编程</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#构造函数"><span class="nav-number">14.1.</span> <span class="nav-text">构造函数</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#new-命令"><span class="nav-number">14.2.</span> <span class="nav-text">new 命令</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Object-create-创建实例对象"><span class="nav-number">14.3.</span> <span class="nav-text">Object.create() 创建实例对象</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#this-关键字"><span class="nav-number">14.4.</span> <span class="nav-text">this 关键字</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#绑定-this-的方法"><span class="nav-number">14.4.1.</span> <span class="nav-text">绑定 this 的方法</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#Function-prototype-call"><span class="nav-number">14.4.1.1.</span> <span class="nav-text">Function.prototype.call()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Function-prototype-apply"><span class="nav-number">14.4.1.2.</span> <span class="nav-text">Function.prototype.apply()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Function-prototype-bind"><span class="nav-number">14.4.1.3.</span> <span class="nav-text">Function.prototype.bind()</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#如何选用"><span class="nav-number">14.4.2.</span> <span class="nav-text">如何选用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#特点总结"><span class="nav-number">14.4.3.</span> <span class="nav-text">特点总结</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#对象的继承"><span class="nav-number">14.5.</span> <span class="nav-text">对象的继承</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#原型对象概述"><span class="nav-number">14.5.1.</span> <span class="nav-text">原型对象概述</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#构造函数的缺点"><span class="nav-number">14.5.1.1.</span> <span class="nav-text">构造函数的缺点</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#prototype-属性的作用"><span class="nav-number">14.5.1.2.</span> <span class="nav-text">prototype 属性的作用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#原型链"><span class="nav-number">14.5.1.3.</span> <span class="nav-text">原型链</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#constructor-属性"><span class="nav-number">14.5.1.4.</span> <span class="nav-text">constructor 属性</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#instanceof-运算符"><span class="nav-number">14.5.2.</span> <span class="nav-text">instanceof 运算符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#构造函数继承"><span class="nav-number">14.5.3.</span> <span class="nav-text">构造函数继承</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#思考"><span class="nav-number">14.5.3.1.</span> <span class="nav-text">思考</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#一、构造函数绑定"><span class="nav-number">14.5.3.2.</span> <span class="nav-text">一、构造函数绑定</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#二、prototype-模式"><span class="nav-number">14.5.3.3.</span> <span class="nav-text">二、prototype 模式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#三、直接继承-prototype"><span class="nav-number">14.5.3.4.</span> <span class="nav-text">三、直接继承 prototype</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#四、利用空对象作为中介"><span class="nav-number">14.5.3.5.</span> <span class="nav-text">四、利用空对象作为中介</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#五、拷贝继承"><span class="nav-number">14.5.3.6.</span> <span class="nav-text">五、拷贝继承</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#非构造函数继承"><span class="nav-number">14.5.4.</span> <span class="nav-text">非构造函数继承</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#思考-1"><span class="nav-number">14.5.4.1.</span> <span class="nav-text">思考</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#一、object-方法"><span class="nav-number">14.5.4.2.</span> <span class="nav-text">一、object() 方法</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#二、浅拷贝"><span class="nav-number">14.5.4.3.</span> <span class="nav-text">二、浅拷贝</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#三、深拷贝"><span class="nav-number">14.5.4.4.</span> <span class="nav-text">三、深拷贝</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#多重继承"><span class="nav-number">14.5.5.</span> <span class="nav-text">多重继承</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#模块"><span class="nav-number">14.6.</span> <span class="nav-text">模块</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#基本的实现方法"><span class="nav-number">14.6.1.</span> <span class="nav-text">基本的实现方法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#封装私有变量：构造函数的写法"><span class="nav-number">14.6.2.</span> <span class="nav-text">封装私有变量：构造函数的写法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#封装私有变量：立即执行函数的写法"><span class="nav-number">14.6.3.</span> <span class="nav-text">封装私有变量：立即执行函数的写法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#模块的放大模式"><span class="nav-number">14.6.4.</span> <span class="nav-text">模块的放大模式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#输入全局变量"><span class="nav-number">14.6.5.</span> <span class="nav-text">输入全局变量</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Object-对象的相关方法"><span class="nav-number">14.7.</span> <span class="nav-text">Object 对象的相关方法</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Object-getPrototypeOf"><span class="nav-number">14.7.1.</span> <span class="nav-text">Object.getPrototypeOf()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Object-setPrototypeOf"><span class="nav-number">14.7.2.</span> <span class="nav-text">Object.setPrototypeOf()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Object-create"><span class="nav-number">14.7.3.</span> <span class="nav-text">Object.create()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Object-prototype-isPrototypeOf"><span class="nav-number">14.7.4.</span> <span class="nav-text">Object.prototype.isPrototypeOf</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#Object-prototype-proto"><span class="nav-number">14.7.5.</span> <span class="nav-text">Object.prototype.__proto__</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#获取原型对象方法比较"><span class="nav-number">14.7.6.</span> <span class="nav-text">获取原型对象方法比较</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#对象的拷贝"><span class="nav-number">14.8.</span> <span class="nav-text">对象的拷贝</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#定时器"><span class="nav-number">15.</span> <span class="nav-text">定时器</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#setTimeout"><span class="nav-number">15.1.</span> <span class="nav-text">setTimeout()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#setInterval"><span class="nav-number">15.2.</span> <span class="nav-text">setInterval()</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#clearTimeout-、clearInterval"><span class="nav-number">15.3.</span> <span class="nav-text">clearTimeout()、clearInterval()</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Albert Guo"
      src="https://inews.gtimg.com/newsapp_ls/0/12122532695/0">
  <p class="site-author-name" itemprop="name">Albert Guo</p>
  <div class="site-description" itemprop="description">郭鹏松的个人博客</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives">
          <span class="site-state-item-count">19</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">6</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="mailto:albert-guo@outlook.com" title="E-Mail → mailto:albert-guo@outlook.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Albert Guo</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
